Ĭ��
���� �������� 0
�뿪��IM������Ʒ�¿ӣ�����3���¹����ҿ�Դ����ߣ������������·��... ��վ�����㽨��
���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��
΢��ɨһɨ��ע��

������Я�̼���Butters������ԭ�⡰�ɻ� | �վ�����200�ڣ�Я�̸�����ȫ�첽����ʵ��������ʱͨѶ�����޶��������Ű档


1������


���ķ�������Я��API����ȫ�첽������ʵ��������������Zuul 1.0ͬ���ܹ�����Ϊ����Netty��ȫ�첽�ܹ���ͨ��RxJavaʵ��ҵ�������첽����������ʽת����ZGC�ȼ��������������ܣ�������������ʵ�ֶ�Э��ͳһ������ģ�黯���š�

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_cover_opti.png

2�����߽���


Butters��Я����������ר�ң�רע�������ܹ���API���ء����ؾ��⡢Service Mesh��������

3��ר��Ŀ¼


������ר��ϵ�����µĵ� 13 ƪ����Ŀ¼���£�


4����������


�����๫˾һ����Я��API����Ҳ��ͬ΢�����ܹ�һ�������Ļ�����ʩ�������汾������2014�ꡣ���ŷ������ڹ�˾�Ŀ����ƽ��������𽥳�ΪӦ�ñ�¶�������ı�׼�����������ġ�ALL IN���ߡ������ʻ������ض����ȣ����ظ����Ź�˾����ҵ���������ܹ���ͬ�ݽ���

���������ϣ���˾΢�������ڷ�չ��NetflixOSSӰ��������ط�������Ҳ�Dzο���Zuul 1.0���еĶ��ο�����

���Ŀɸ���Ϊ�ĵ㣺

  • 1��server����Tomcat NIO + AsyncServlet��
  • 2��ҵ�������������̳߳أ��ֽ׶ε�������ģʽ��
  • 3��client����Apache HttpClient��ͬ�����ã�
  • 4������������Archaius����̬���ÿͻ��ˣ���Hystrix���۶���������Groovy���ȸ���֧�֣���

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_1.png

������֪��ͬ�����������̣߳�ϵͳ������IOӰ��������Ϊ��ҵ������Zuul��������Ҳ���ǵ������㡪��ͨ������Hystrix����Դ�������������������ϣ���IO������һ����Χ�ڣ������۶ϲ��ԣ�����ǰ�ͷŲ����߳���Դ�����մﵽ�ֲ��쳣��Ӱ��ȫ�ֵ�Ŀ�ġ�

�����Ź�˾ҵ���ķ�չ����������Ч���𽥼�����

��Ҫԭ�������������ı䶯��

  • 1��ҵ��������������Ϊ���������㣬����������ת�ع��ڣ���IO��Ϊ��̬��
  • 2��������ģ�������ֲ��쳣��̬��������΢�����쳣��ɢ�����ԣ��̳߳ؿ��ܳ��ڴ����ǽ���״̬��

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_2.png

ȫ�첽������Я��API���ؽ�����һ�����Ĺ����㣬����Ҳ���ɴ�չ������һ�����������ط����Ĺ�����ʵ�����ص������������Ż���ҵ����̬�������ܹ������������ȡ�

5�����������غ�������1���첽��������


ȫ�첽 = server���첽 + ҵ�������첽 + client���첽


����server��client�ˣ�����ѡ����Netty������NIO/Epoll + Eventloop���������¼����������ơ�

������������ҵ�����̵��첽���������첽����������

  • 1��ҵ��IO�¼���������У�顢������֤���漰Զ�̵��ã�
  • 2������IO�¼�������ȡ���˱��ĵ�ǰxx�ֽڣ�
  • 3������ת��������TCP���ӣ�HTTP������

�����ϣ��첽��������ͬ�������ơ���д�϶�������һЩ��

��ν�����ѣ�һ��������

  • 1����������&״̬ת����
  • 2���쳣���������������쳣�볬ʱ��
  • 3�������Ĵ��ݣ�����ҵ����������trace log��
  • 4���̵߳��ȣ�
  • 5���������ơ�

������Netty�������ڣ���ByteBuf�����������ƵIJ����ƣ������������ڴ�й©��Χ����Щ���⣬���������˶�Ӧ��Χ���ܣ�����Ŭ����ҵ������Ĩƽͬ��/�첽���죬���㿪����ͬʱĬ�϶������ݴ�����֤�������尲ȫ�������Ͻ�����RxJava����Ҫ��������ͼ��ʾ��

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_3.png

Maybe��

  • 1��RxJava���������࣬��ʶ�������������ҽ���һ�����󷵻ء��쳣����״̬��
  • 2����Ӧʽ����������״̬�����ƣ��Դ��쳣��������ʱ���̵߳��ȵȷ�װ��
  • 3��Maybe.empty()/Maybe.just(T)������ͬ��������
  • 4��������RxJavaPlugins�����������߼���װ��

Filter��

  • 1������һ��������ҵ���߼���ͬ��&�첽ҵ��ͳһ�ӿڣ�����Maybe��
  • 2���첽��������Զ�̵��ã�ͳһ��װ�����漰�߳��л���ͨ��maybe.obesrveOn(eventloop)�лأ�
  • 3���첽filterĬ�����ӳ�ʱ���������������������Դ�����

public interface Processor<T> {    
    ProcessorType getType();
    
    int getOrder();
    
    boolean shouldProcess(RequestContext context);
    
    //����ͳһ��װΪMaybe    
    Maybe<T> process(RequestContext context) throws Exception; 
}


public abstract class AbstractProcessor implements Processor { 
    //ͬ��&����Ӧ���̳д˷��� 
    //����������ҵ������ 
    protected void processSync(RequestContext context) throws Exception {}

    //ͬ��&����Ӧ���̳д˷�������������
    //�������������⡢δͨ��У��ʱ�ľ�̬��Ӧ
    protected T processSyncAndGetReponse(RequestContext context) throws Exception {
        process(context);
        return null;
    };

    //�첽���̳д˷���
    //��������֤����Ȩ���漰Զ�̵��õ�ģ��
    protected Maybe<T> processAsync(RequestContext context) throws Exception 
{
        T response = processSyncAndGetReponse(context);
        if (response == null) {
            return Maybe.empty();
        } else {
            return Maybe.just(response);
        }
    };

    @Override
    public Maybe<T> process(RequestContext context) throws Exception {
        Maybe<T> maybe = processAsync(context);
        if (maybe instanceof ScalarCallable) {
            //��ʶͬ������������������װ
            return maybe;
        } else {
            //ͳһ�ӳ�ʱ��Ĭ�Ϻ��Դ���
            return maybe.timeout(getAsyncTimeout(context), TimeUnit.MILLISECONDS,
                    Schedulers.from(context.getEventloop()), timeoutFallback(context));
        }
    }

    protected long getAsyncTimeout(RequestContext context) {
        return 2000;
    }

    protected Maybe<T> timeoutFallback(RequestContext context) {
        return Maybe.empty();
    }

�������̣�

  • 1�����������������ƣ���Ϊinbound��outbound��error��log�Ľ׶Σ�
  • 2�����׶���һ������filter���ɣ�
  • 3��filter˳��ִ�У������쳣���жϣ�inbound�ڼ�����filter����responseҲ�����жϡ�

public class RxUtil{
      //����ij�׶Σ���Inbound���ڵĶ���filter����Callable<Maybe<T>>��
      public static <T> Maybe<T> concat(Iterable<? extends Callable<Maybe<T>>> iterable) {
          Iterator<? extends Callable<Maybe<T>>> sources = iterable.iterator();
          while (sources.hasNext()) {
              Maybe<T> maybe;
              try {
                  maybe = sources.next().call();
              } catch (Exception e) {
                  return Maybe.error(e);
              }
              if (maybe != null) {
                  if (maybe instanceof ScalarCallable) {
                      //ͬ������
                      T response = ((ScalarCallable<T>)maybe).call();
                      if (response != null) {
                          //��response���ж�
                          return maybe;
                      }
                  } else {
                      //�첽����
                      if (sources.hasNext()) {
                          //��sources�����ص�������filter�ظ����߼�
                          return new ConcattedMaybe(maybe, sources);
                      } else {
                          return maybe;
                      }
                  }
              }
          }
          return Maybe.empty();
      }
  }

public class ProcessEngine{
      //�����׶Σ�����Ĭ�ϳ�ʱ����������
    private void process(RequestContext context) {
          List<Callable<Maybe<Response>>> inboundTask = get(ProcessorType.INBOUND, context);
          List<Callable<Maybe<Void>>> outboundTask = get(ProcessorType.OUTBOUND, context);
          List<Callable<Maybe<Response>>> errorTask = get(ProcessorType.ERROR, context);
          List<Callable<Maybe<Void>>> logTask = get(ProcessorType.LOG, context);
  
         RxUtil.concat(inboundTask)    //inbound�׶�                    
              .toSingle()        //��ȡresponse                          
              .flatMapMaybe(response -> {
                  context.setOriginResponse(response);
                  return RxUtil.concat(outboundTask);
              })            //����outbound
              .onErrorResumeNext(e -> {
                  context.setThrowable(e);
                  return RxUtil.concat(errorTask).flatMap(response -> {
                      context.resetResponse(response);
                      return RxUtil.concat(outboundTask);
                  });
              })            //�쳣������error�������½���outbound
              .flatMap(response -> RxUtil.concat(logTask))  //��־�׶�
              .timeout(asyncTimeout.get(), TimeUnit.MILLISECONDS, Schedulers.from(context.getEventloop()),
                      Maybe.error(new ServerException(500, "Async-Timeout-Processing"))
              )            //ȫ�ֶ��׳�ʱ
              .subscribe(        //�ͷ���Դ
                      unused -> {
                          logger.error("this should not happen, " + context);
                          context.release();
                      },
                      e -> {
                          logger.error("this should not happen, " + context, e);
                          context.release();
                      },
                      () -> context.release()
              );
      }   
  }

6�����������غ�������2����ʽת��&���߳�


��HTTPΪ�������Ŀɻ���Ϊinitial line/header/body�������ɲ��֣�
���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_4.png

��Я�̣����ز�ҵ�����漰body����Ϊ����ȫ���棬���Խ�����header����ֱ�ӽ���ҵ�����̡�

�ڴ�ͬʱ���������յ�body���֣�

  • 1��������upstreamת����������ֱ��ת����
  • 2��������Ҫ�����ݴ棬��ҵ�����̴������ϣ�ͬinitial line/headerһ�����ͣ�
  • 3����upstream����Ӧ�Ĵ�����ʽ��Ȼ��

�Ա���������HTTP���ĵķ�ʽ������������

  • 1����������ҵ�����̣���ζ��upstream�������յ�����������Ч�������������������ӳ٣�
  • 2��body�������ڱ�ѹ�����ɽ��������������ڴ濪����

��˵���������ܣ�����ʽ�ķ�ʽҲ�����������������̵ĸ��Ӷ�

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_5.png

����ʽ�����£�Netty Server�˱����롢����ҵ���߼���Netty Cerver�˱����롢����ҵ���߼������������໥���������Դ���������HTTP������

��ȡ��ʽ��������������ͬʱ���ڶ������ڣ����������ѿɹ���Ϊ�������㣺

  • 1���̰߳�ȫ��������ͬ���������ò�ͬ�̣߳����漰�����ĵIJ����޸ģ�
  • 2�����׶�����������Netty Server��������һ�������������жϣ���ʱ�Ѿ�������upstream����ôupstream����Э��ջ���߲����ģ�Ҳ������֮�ر����ӣ�
  • 3����Ե��������������upstream������δ�������������·�����404/413����ѡ���������͡�����Э��ջ���������ܹ����ã�����ѡ����ǰ��ֹ���̣���Լ��Դ����ͬʱ�������ӣ��ٱ��磬upstream���յ�������δ��Ӧ����ʱNetty ServerͻȻ�Ͽ���Netty Client�Ƿ�ҲҪ��֮�Ͽ����ȵȡ�

������Щ���������Dz����˵��̵߳ķ�ʽ���������ƣ�

  • 1�������İ���Eventloop��Netty Server/ҵ������/Netty Client��ͬ��eventloopִ�У�
  • 2���첽filter����IO���Ĺ�ϵ������ʹ�ö����̳߳أ����ں��ô����ϱ����лأ�
  • 3����������Դ����Ҫ���̸߳��루�����ӳأ���

���õ��̵߳ĺô���

  • 1���ž��˲������⣬�ڶ��׶���������Ե�������⴦��ʱ������ϵͳҲ����ȷ����״̬�£���Ч�����˿����Ѷ������գ�
  • 2�������߳��л���һ���̶���Ҳ�ܹ��������ܡ�

��֮���Եģ���Ϊworker�߳������٣�һ������CPU��������eventloop�ڱ�����ȫ�ž�IO���������򽫶�ϵͳ�������ɻ����Դ�����

7�����������غ�������3�������Ż�


�ڲ����������أ�����������cookie/query���ֶΣ����ޱ�Ҫ������ǰ�����ַ�������

�����ڴ�&�㿽��������ǰ����ʽת�������ƣ���һ������ϵͳ�ڴ濪��

ZGC����Ŀ��TLSv1.3��������JDK11��JDK8֧�����Խ�����8u261�汾��2020.7.14������ȻҲ����һ����GC�㷨�����˳��ԣ�ʵ�ʱ���Ҳȷʵ����ʢ������CPUռ������������������GC��ʱ�½��dz����ԡ�

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_6.png

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_7.png

���Ƶ�HTTP�����룺HTTP���ƾ���ʷ����֮Э�������Ŀ����ԣ����������ࡰ��ʵ����������Ӱ���ɹ��ʣ�������в��վ��ȫ�����������ӣ�

��������������������������413����uri������414������ASCII�ַ���400�������⣬һ��WebServer��ѡ��ֱ�Ӿܾ������ض�Ӧ״̬�롣����ֱ��������ҵ�����̣�����������ͳ�ơ�������Ϊ�������϶����Ƚ��鷳����չ�����룬����������Ҳ�ܹ�����·�����̣����԰��������DZ��������������⡣

�������ˣ���request smuggling��Netty 4.1.61.Final�޸���2021.3.30����������չ�����룬�����Զ�����У���߼����ð�ȫ�����ܹ��������ء�

8������ҵ����̬


��Ϊ������ͳһ�����������տڵ㣬���ضԹ�˾�ļ�ֵ��Ҫ�����������棺

  • 1�����ͬ���绷�������ͳ�����������&��������������&�칫����IDC�ڲ���ͬ��ȫ����ר�ߵȣ�
  • 2����Ȼ�Ĺ���ҵ��������������ȫ&��֤&������·��&�Ҷȡ�����&�۶�&����������&�澯&���ϵȣ�
  • 3����Ч���������������ơ�

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_8.png

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_9.png

����չ��������ϸ�ֳ�����

˽��Э�飺

  • 1�����տڵĿͻ��ˣ�APP�����ɿ��ܲ������û�������HTTP������ͨ��˽��Э�飨SOTP���ķ�ʽ���������ˣ�
  • 2��ѡַ���棺��ͨ���������·�IP���ž�DNS�ٳ֣�������Ԥ�ȣ����Զ�����ѡַ���ԣ����������������������������л���
  • 3��������ʽ�ϣ��ٸ���������Э���壻��ͳһ����&ѹ��&��·���ã���Э�������ڴ�������ͳһת������ҵ��͸����

��·�Ż������������������㣬��Զ�����û��ͽ����ʣ��������ֿ������������⡣ͬʱ����Ϊ��������IDC�ǿɿص����ˣ�������·ѡ����Э�齻��ģʽ�϶��и������Ż��ռ䡣

���ض�������ڰ��������䡢�ͽ����ʲ��Եȣ����ض���ģʽ�£����أ����������谴��ҵ��ά�ȵ�shardingKey���з�������userId������ֹ�ײ����ݳ�ͻ��

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_10.png

9��������������


��ͼ�ܽ����������صĹ���״̬��
���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_11.png

������Ӧ���ǵ�ҵ�����̣���ͬ������APP��H5��С���򡢹�Ӧ��������ͬЭ�飨HTTP��SOTP�����������ɸ��ؾ����������أ�����ϵ��ҵ���߼��Ĵ���������ת�������˷��񡣾����˵ڶ��µĸ����󣬺���ҵ�������ܡ��ȶ����϶��õ��˽Ϻõ�������

��һ���棺���ڶ�����/Э���Ĵ��ڣ��������ذ�ҵ�񻮷֣������˶�����Ⱥ�IJ�����ҵ�����죨·�����ݡ�����ģ��������ͨ������������֧���������ŷ�֧�������ӣ���������ά���Ӷ�Խ��Խ�ߡ�ϵͳ�����У����Ӷ�����Ҳ��ζ�ŷ��ա����ζԶ�Э�顢����ɫ������ʵʩͳһ�����������Խϵ͵ijɱ�������Ϊ��ҵ������ƻ����أ���Ϊ�����Ǻ�һ�׶εĹ������ġ�

��������Ҳ�Ƚ�ֱ�۵���ͼ�л��˳�����

  • 1����Э���ϼ��ݴ����������ϴ�������һ�׿����£�
  • 2�������������棬���������صIJ������Խ���ͳһ������

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_12.png

10��������������1��������


Э�����ݵ������������ʣ��������Բο�Tomcat��HTTP/1.0��HTTP/1.1��HTTP/2.0�ij�����HTTP������Ȼ�ڸ����汾�������˴���feature������������ҵ�񿪷�ʱͨ����֪������Щ����������HttpServletRequest�ӿڵij�����

��Я�̣��������ԵĶ�����������Ӧģʽ����״̬Э�飬����������Ҳ���Ի���ΪԪ���ݡ���չͷ��ҵ�����������֣����˿��ԱȽϷ����ؽ������Ƶij��ԡ�

��Ӧ������������������������

  • 1��Э�����������������β�ͬЭ���ı����롢����ģʽ����TCP���ӵĴ����ȣ�
  • 2������ͨ���м�ģ�����ӿ���ҵ�������м�ģ�����ӿڱ��̣����õؾ۽���Э����Ӧ��ҵ��������ȥ��

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_13.png

11��������������2��·��ģ��


·��ģ���ǿ�������������Ҫ���ɲ���֮һ��

���˹������ء���������ӳ����ϵ��������������������ģ�͸�����
{
      //ƥ�䷽ʽ
      "type": "uri",
      
      //HTTPĬ�ϲ���uriǰ׺ƥ�䣬�ڲ�ͨ�����ṹѰַ��˽��Э�飨SOTP��ͨ������Ψһ��ʶ��λ��
      "value": "/hotel/order",
      "matcherType": "prefix",
      
      //��ǩ������
      //����portal��Ȩ�޹����������߼����У��簴����/�Ǻ��ģ���
      "tags": [
          "owner_admin",
          "org_framework",
          "appId_123456"
      ],
      "properties": {
          "core": "true"
      },
      
    //endpoint��Ϣ
      "routes": [{
          //condition���ڶ���·�ɣ��簴app�汾���֡���query�ط�����
          "condition": "true",
          "conditionParam": {},
          "zone": "PRO",
          
          //����������ַ��Ȩ�����ڻҶȳ���
          "targets": [{
              "url": "http://test.ctrip.com/hotel",
              "weight": 100
          }
        ]
      }]
  }

12��������������3�������


ģ�������ǿ���������һ�����IJ��֡�

���������ؼ���ר��(ʮ��)������Netty��Я�̸����������첽����ʵ��_14.png

���������ش���������Ԥ���˶����׶Σ���ͼ���÷�ɫ�������������۶ϡ���������־��ͨ�ù��ܣ�����ʱ��ͬ��������ִ�е�ҵ�������ɿ�����ͳһ�·������ܱ����������ڲ��ж����Ĵ���ģ�飬���������ⶨ���˹��ܶ�Ӧ��ִ���������������Ҷȱ���������������ʽ�ȡ����ֱ��ŷ�ʽҲ�ڲ��汣֤��ģ�����Ľ��
{
      //ģ�����ƣ���Ӧ�����ڲ�ij������ģ��
      "name": "addResponseHeader",
      
      //ִ�н׶�
      "stage": "PRE_RESPONSE",
      
      //ִ��˳��
      "ruleOrder": 0,
      
      //�Ҷȱ���
      "grayRatio": 100,
      
      //ִ������
      "condition": "true",
      "conditionParam": {},
      
      //ִ�в���
      //����${}��ʽ������ģ�壬���ڻ�ȡ����ʱ����
      "actionParam": {
        "connection": "keep-alive",
        "x-service-call": "${request.func.remoteCost}",
        "Access-Control-Expose-Headers": "x-service-call",
        "x-gate-root-id": "${func.catRootMessageId}"
      },
      
      //�쳣������ʽ�������׳�������
      "exceptionHandle": "return"
   }

13��������


���س����������Ǹ��༼������ƽ̨�ϵ��ȵ㣬����Ҳ�dz��ḻ����չ�硢�����ֵ�Zuul1.0�������ܵ�Nginx�����ɶȸߵ�SpringCloud Gateway������������Istio�ȵȡ����վ���ѡ�͵Ļ��Ǹ���˾������ҵ�񱳾��뼼����̬��Ҳ�����ˣ���Я������ѡ�������еĵ�·��

�������Ϸ�չ������Ҳ�ڳ���̽������������ͬҵ�����صĹ�ϵ����Э�������أ�HTTP3������ServiceMesh�Ĺ�ϵ�ȵȣ����ϻ�ӭ����Ȥ��ͬѧһ���������ۡ�

14�������


[1] ����������������TCP���ؼ���ʵ���ܽ�
[2] �����ڼ��ƶ��˽��������صļ����ݽ�֮·
[3] ϲ�����������ڼ�API���ؼ���ʵ��
[4] С��С������120�������ӽ������ļܹ��ݽ�
[5] Bվ����΢������API���ش�0��1���ݽ�֮·
[6] ȥ�Ķ����Ƶ�������ҵ�����ؼ���ʵ��
[7] �ن��£�һ���Ӵ�������Java��NIO�;���IO������
[8] ʷ����ǿJava NIO���ţ����Ĵ����ŵ������ģ�������ƪ��
[9] Java��BIO��NIO���Ѷ����ô���ʵ�����㿴���ٲ�����ת�У�
[10] ʷ����ͨ��Netty�������ų��ģ��������ܡ������������ʵս
[11] �������ţ�ĿǰΪֹ��͸���ĵ�Netty������ԭ���Ϳ��ܼܹ�����

��ʱͨѶ�� - ��ʱͨѶ������������ ��Դ�� - ��ʱͨѶ������������

��һƪ����Ϊ��֪����������(ʮ��)����ɽ֮�£�һ���������󱳺��ļ�������

��������¼�����¼���ר��

�Ƽ�����
����¥�� ×
ʹ��΢�Ŵ��ͣ� ʹ��֧�������ͣ�

���ض���