Dubboソースのサービスリファレンス

7702 ワード

全体的なプロセス


ReferenceBeanはFactoryBeanとInitializingBeanインタフェースを実現しているので、Beanを初期化するときにReferenceBean#afterPropertiesSetメソッドが実行されます
ReferenceBean#afterPropertiesSet => 
    ReferenceBean#getObject => 
        ReferenceConfig#get =>
            ReferenceConfig#init =>
                ReferenceConfig#createProxy =>
                    Protocol$Adaptive#refer =>
                        ProtocolFilterWrapper#refer =>
                            ProtocolListenerWrapper#refer => 
                                RegistryProtocol#refer =>
                                    RegistryProtocol#doRefer =>
                                        ZookeeperRegistry#register( consumer ) =>
                                        RegistryDirectory#subscribe( providers routers configurators , Invoker)

                                        Cluster$Adaptive#join =>
                                            MockClusterWrapper#join =>
                                                FailoverCluster#join(return new FailoverClusterInvoker) =>
                                                return new MockClusterInvoker =>

                                        ProviderConsumerRegTable#registerConsumer =>
                                        return Invoker



-----------------------------   RegistryDirectory#subscribe   Invoer   ----------------------
RegistryDirectory#subscribe =>
    FailbackRegistry#subscribe =>
        AbstractRegistry#subscribe =>  
        ZookeeperRegistry#doSubscribe =>
            AbstractZookeeperClient#addChildListener =>
            ZookeeperRegistry#notify =>
                AbstractRegistry#doNotify =>
                    RegistryDirectory#notify =>
                        RegistryDirectory#refreshInvoker =>
                            RegistryDirectory#toInvokers=>
                                new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl) =>
                                newUrlInvokerMap.put(key, invoker)


Consumer登録


この作業はReferenceConfig#createProxyメソッドで完了し、コアコードは次のようになります.
//   REF_PROTOCOL   Protocol$Adaptive
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
  • Protocol$Adaptive#referメソッドでは、SPIのAOP特性に応じてProtocolFilterWrapperが返されます.ProtocolListener Wrapperがパッケージされています.ProtocolListener WrapperはRegistryProtocolがパッケージされています.したがって、呼び出し順序は次のとおりです.ProtocolFilterWrapper=>ProtocolListener Wrapper#refer=>RegistryProtocol#refer RegistryProtocol , ProtocolFilterWrapper ProtocolListenerWrapper
  • RegistryProtocol#referメソッドでConsumerノード登録、ノード傍受、Invoker生成作業
    RegistryProtocol#refer =>
        RegistryProtocol#doRefer =>
            ZookeeperRegistry#register( consumer ) =>
    
  • を完了する.

    ノードリスニング

    consumer://10.10.129.164/org.apache.dubbo.demo.DemoService?application=dubbo-demo-api-consumer&category=providers,configurators,routers&check=false&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&lazy=false&methods=sayHello,asyncSay&pid=32780&side=consumer&sticky=false&timestamp=1570954083348
    

    ノードリスニングの概略手順は次のとおりです.
  • 各consumerは1つの唯一のurlとRegistryDirectoryオブジェクトに対応し、RegistryDirectoryはNotifyListenerインタフェース
  • を実現した.
  • RegistryDirectoryごとにChildListenerが対応する.ChildListenerは匿名の内部クラスであり、主な機能はZookeeperRegistry#notifyメソッド
  • を実行することである.
  • 各ChildListenerは、TargetChildListener、すなわちCuratorZookeeperClientに対応する.CuratorWatcherImplは、CuratorWatcherおよびTreeCacheListenerインタフェース
  • を実現する
  • 上記で作成するTargetChildListenerオブジェクトをpathのリスナー(path=/dubbo/service/provisers,/dubbo/service/routers,/dubbo/service/configurations)
  • とする.
  • AbstractRegistry#notifyメソッドを実行し、providerが変化するたびにInvokerオブジェクト
  • をリフレッシュするRegistryDirectory#notifyメソッドを実行する.
    dubboのノードリスニングメカニズムは気持ち悪いので、このようにして、1つのノードが変化したときに、どのような操作を実行しますか?

    Invokerの作成


    RegistryDirectory#notifyメソッドは、主にproviderUrlに基づいてInvokerオブジェクトを生成します.
    RegistryDirectory#notify
  • はconfigurationsタイプのurlを処理し、このurlがあれば、このurlに基づいてConfiguratorオブジェクトを生成する.
  • routersタイプのurlを処理し、このurlがある場合、このurlに基づいてRouterオブジェクトを生成し、RouterChainに追加する.
  • providersタイプurlを処理する、すなわちRegistryDirectory#refreshOverrideAndInvoker
  • を実行する.
    RegistryDirectory#refreshOverrideAndInvoker
  • コンフィギュレーション情報は、コンフィギュレーションオブジェクトmerge overrideDirectoryUrlに従って、
  • に相当する.
  • RegistryDirectory#refreshInvokerメソッド
  • を実行
    RegistryDirectory#refreshInvoker
  • RegistryDirectory#toInvokers
  • RegistryDirectory#mergeUrl
  • new InvokerDelegate()

  • new InvokerDelegate() invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl);
  • protocolを先に通過します.referは包装されたDubboProtocol
  • を取得した.
  • InvokerDelegateオブジェクトを作成する
  • 実行InvokerWrapperの構築方法
  • Invokerはキャッシュ
  • に入れる.

    Clusterへの参加


    前のステップでInvokerオブジェクトに戻ると、Cluster$Adaptive#joinメソッドを実行し、SPIに従ってFailover Clusterを取得し、MockClusterWrapperパッケージを使用します.
    Cluster$Adaptive#join =>
        MockClusterWrapper#join =>
            FailoverCluster#join => 
                new FailoverClusterInvoker =>
            return MockClusterInvoker
    

    プロキシの作成


    ReferenceConfig#createProxyメソッドでは、Invokerオブジェクトを作成した後、Invokerをインパラメータとしてプロキシオブジェクトを作成します.
    (T) PROXY_FACTORY.getProxy(invoker)
    

    ProxyFactory$Adaptive#getProxy => StubProxyFactoryWrapper#getProxy => AbstractProxyFactory#getProxy => JavassistProxyFactory#getProxy => return proxy
    JavassistProxyFactory#getProxy
    public  T getProxy(Invoker invoker, Class>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }
    

    最新の赤で生成されたエージェントクラスは次のとおりです.
    public class proxy0 implements ClassGenerator.DC, EchoService, DemoService{
      public static Method[] methods;
      private InvocationHandler handler;
    
      public String sayHello(String paramString){
        Object[] arrayOfObject = new Object[1];
        arrayOfObject[0] = paramString;
        Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);
        return ((String)localObject);
      }
    
      public Object $echo(Object paramObject)
      {
        Object[] arrayOfObject = new Object[1];
        arrayOfObject[0] = paramObject;
        Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);
        return ((Object)localObject);
      }
    
      public proxy0(){
      }
    
      public proxy0(InvocationHandler paramInvocationHandler){
        this.handler = paramInvocationHandler;
      }
    }
    

    InvokerInvocationHandlerはJavaのInvocationHandlerインタフェースを実現しているので、JDKダイナミックエージェントのinvokerメソッドにも適用されます.
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
    
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }
    

    すなわち、エンドユーザがプロキシオブジェクトを介してサービスを呼び出す場合、実際にInvoker#invokerメソッドを実行する