Dubbo study notes Source of Consumer & configuration changes start listening

  In the previous article, the share recorded ExtensionLoader extension mechanism, the publishing process services, Netty start listening content services, compared to today to write client-side publishing service, start is quite clear, well-understood. 

      Client ref generation, individuals also sort for a long time, relatively speaking server, mostly a few places too much trouble:

     1. during start-up clients, involving several of zk path, data change subscriptions, multiple listener, often confused.

         2. Many listeners are java8 inside lamada expression, to write fast, it will not be easy to understand debugging

         3. Client, involves covering reload configuration parameters to provider -> consumer - the sequence coverage values ​​for the dynamic distribution center configs>, provided to take the inside of the final subject. 

 

   A, Client calls diagram

                      

            In ReferenceConfig following Protocol process which, first there is a RegisterProtocol registration agreement, this is also very important, the first in which the registration agreement done a lot of work, and then perform the Protocol on the inside, the implementation of specific interaction protocols.

 

Two, RegistryProtocol of doRefer

     Client starts inside the main flow doRefer method RegistryProtocol class.

private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
        RegistryDirectory <T> Directory = new new RegistryDirectory <T> (type, URL);   // 1. Directory is a key-based client-initiated, Invoker responsible for generating, monitoring and other configuration information changing operation, 
        directory.setRegistry (Registry);
        directory.setProtocol(protocol);
        // all attributes of REFER_KEY
        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
        URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
        if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) {
            directory.setRegisteredConsumerUrl(getRegisteredConsumerUrl(subscribeUrl, url));
            registry.register (directory.getRegisteredConsumerUrl ()); // 2. ZK generation path above, registration Consumer 
        }
        directory.buildRouterChain (subscribeUrl); // 3. actually building RouterChain, the default is four 
        directory.subscribe (subscribeUrl.addParameter (CATEGORY_KEY,
                PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));   // 4. Feed perform directory, many important starting logic inside this method 

        Invoker An invoker = cluster.join (directory); // 5. The directory to be packaging, together with mock, failover function 
        ProviderConsumerRegTable.registerConsumer (An invoker, URL, subscribeUrl, Directory);   // 6. The pair invoker, directory information simple polymerization, into the local Map 
        return An invoker;
    }

 Client inside, RegistoryDirectory is a more important, a package of the node, the configuration change process, the actual call start Invoker like logic.

 1. Notes 1. RegistoryDirectory example out a new new, less internal logic, the main data is converted to a base url

 2. Note 2. The conumser path, registered in zk above.

 3. Note 3. Call ExtensionLoader acquired RouterFactory of ActiveExtension (), and then call the factory method, obtaining the actual Router, router ranking generation chain. Followed by: MockInvokersSelector, TagRouter, AppRouter, ServiceRouter, function is also well understood, the role of the Router, is to obtain a list of provider may be called. Tag, App, Service 3 Ge Router will monitor data changes ZK's data. But there is no start monitoring, the back talk anymore.

4. 4. Note that line, but much later action, presumably comprising: a) zk registered on various data, path monitor b) actually interact protocol initialization, c) start a network client, server connection

Note 5. The packaging directory, with mock, failover functionality. This cluster line is adaptive, which by default will enter MockClusterWrapper join method. 

 

Three, RegisterDirectory class

     RegisterDirectory this class, mainly zk listener, and then perform the appropriate action. Of course, also here the bottom dobboprotocol start, netty client is started by the operation of the method of the listener inside.

    RegisterDirectory class, there are several major methods: 1, subscribe (url) 2, notify (List urls) 3, refreshOverrideAndInvoker (List urls) 4.refreshInvoker (List urls), call relationship is: 1 -> 2 -> 3 -> 4, one by one to talk about such a step by step following the call.

 

 1. subscribe method

接上面的方法:  directory.subscribe(subscribeUrl.addParameter(CATEGORY_KEY,  PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY)); 

public void subscribe(URL url) {
        setConsumerUrl (URL); // NOTE 1. Set the consumer URL 
        CONSUMER_CONFIGURATION_LISTENER.addNotifyListener ( the this ); // NOTE 2. This directory into cunsumer config listener, 
        serviceConfigurationListener = new new ReferenceConfigurationListener ( the this , URL); // Comment 3. the monitor demoservice config 
        registry.subscribe (URL, the this ); // NOTE 4. the listener config, provider, router 3 th path, and calls notify method 
    }

 Notes 1. Save the consumer's url down.

 Notes 2, 3 and notes, two are present as a directory listener, data to monitor changes in the above zk. 

   Note 2, is listening: data change /dubbo/config/demo-consumer.configurators of, demo-consumer is a registered name dubbo client applications

  Notes 3, listening is the data change /dubbo/config/org.apache.dubbo.demo.DemoService.configurators. Here is the name of the interface demoService

  For more than one service is, consumer application name is the same, the interface is changing, so note 2 is added to this directory listener arrays, multiple directory with a path data monitor data changes, Note 3 is another new one ReferenceConfigureListener, data changes each Service interfaces, each direcotry to listen. After the data changes, you are calling RegistryDirectory of refreshInvoker method. When the configuration changes, see if refresh the Invoker

 Notes 4, registry here is ZookeeperRegistry, I would go to listen and get the path below nodes. Listening path is: /dubbo/org.apache.dubbo.demo.DemoService/providers, / dubbo / org.apache.dubbo.demo.DemoService / configurators, / dubbo / org.apache.dubbo.demo.DemoService / routers, That monitor provider, change configurators, routers 3 nodes following sub-node.

Monitor the implementation of the method is ZookeeperRegistry.this.notify. In Note 4 which will eventually perform RegisterDirectory inside the notify (List urls) method.

 

  2. notify(List urls)

    notify method, Invoker the beginning and start listening to configuration changes, will re-use this method. Will cover the protocol conversion, configuration, start the Invoker.

   Reference urls notify the method, whether it is the first time a manual call (the first call from the registry after the acquisition), or a subsequent node zk because the path of change, listener calls, urls are the source of the data path of zk.

 public synchronized void notify(List<URL> urls) {
        Map<String, List<URL>> categoryUrls = urls.stream()
                .filter(Objects::nonNull)
                .filter(this::isValidCategory)
                .filter(this::isNotCompatibleFor26x)
                .collect(Collectors.groupingBy(url -> {
                    if (UrlUtils.isConfigurator(url)) {
                        return CONFIGURATORS_CATEGORY;
                    } else if (UrlUtils.isRoute(url)) {
                        return ROUTERS_CATEGORY;
                    } else if (UrlUtils.isProvider(url)) {
                        return PROVIDERS_CATEGORY;
                    }
                    return "";
                }));   // 1 stream series of operations for checking filter url, packet
        
        // The following code lines configs, routers, providers are data processing 
        List <the URL> configuratorURLs = categoryUrls.getOrDefault (CONFIGURATORS_CATEGORY, Collections.emptyList ());
         the this .configurators = Configurator.toConfigurators (configuratorURLs) .orElse ( the this . configurators);
        List<URL> routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList());
        toRouters (routerURLs) .ifPresent ( the this :: addRouters); // 2. Routers node changes, the new router will rejoin the route 
        
        List <the URL of> = providerURLs categoryUrls.getOrDefault (PROVIDERS_CATEGORY, Collections.emptyList ()); // 3 . providers will continue to change the transmission 
        refreshOverrideAndInvoker (providerURLs); // 4. refresh configuration data, and restart Invoker (if necessary) 
    }

RegisterDirectory class notify method, after the change of path processing node, since the node has a certain path conversion process inside ZookeeperRegister notify method, it is not the original path node.

Into the reference urls, config, router protocol is empty (no data), Provider protocol is protocol specific release, such as the example of dubbo. subsequent empty will be identified, special handling.

The above code: 

   Notes 1. url check list, filtered, and then divided into config, router, provider 3 packets map

   Note 2. If the router changes the routing node, the new data from the router at the router generates, generated before addition of 4-chain active routing inside.

   Notes 3. If there is a change provider node, then get url 

   Notes 4. Call the underlying method, the configuration refresh, if necessary, restart the Invoker.

 

 3. refreshOverrideAndInvoker

    This method which calls on the two methods. First call overrideDirectoryUrl (), the node is washed successively with /dubbo/org.apache.dubbo.demo.DemoService/configurators path configuration, /dubbo/config/consumer.configurators the configuration data, / dubbo / config / org.apache.dubbo .demo.DemoService.configurators the original data consumer configured to adjust the url.   

Private  void refreshOverrideAndInvoker (List <the URL of> urls) {
         // mock ZooKeeper: // ? xxx = mock return null 
        overrideDirectoryUrl (); // 1.-by-call registry configuration inside, covering the original url, url composition of the latest release into overrideDirectoryUrl storage 
refreshInvoker (urls);. // 2 The provider urls, refresh Invoker
}

 

4.  refreshInvoker(urls); 

    refreshInvoker long code, and subcode, not posted, mainly to three operations.

   1.   Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);   

          This line is based on providerUrls, inside toInvoker method, called again almost over configuration override logic. Finally, if there is configured to modify, to regenerate Invoker, not to use the old Invoker. At the same time return the new url <-> Invoker map map

   2.  this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers;   

      This line is that if there are service groups, provider under the packet is to package StaticDirectory, consisting of a Invoker, returned. 

       For example, service Demo, divided into Group A, GroupB, 1,2,3 lower GroupA, GroupB there 2,4,5 lower, then the groupA, GroupB are packaged as a Invoker, is 2 Invoker.

     When the actual call, first with GroupA, GroupB, to routing, load balancing once the election to Group A, and then in Group A, routing, load time, select a node, 2, 3 below to provide services.

  3.  destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap);  

        This line of code is to look at the old url exists in the new map inside, there is destruction url corresponding Invoker. This is easy to understand, for example, there is a provider is down, it is necessary abatement. In addition, with 1provider configuration changes, the new and the old url is not the same, the old will be destroyed, because the new url will generate a Invoker.

 

Third, the monitoring path configured to perform a method and Consumer end

      Respectively addChildListener AbstractZookeeperClient class (), addListener addDataListener () method, ZookeeperDynamicConfiguration class () method to monitor the print key, group, listener.

      Monitoring path changes:

        /dubbo/org.apache.dubbo.demo.DemoService/providers

   /dubbo/org.apache.dubbo.demo.DemoService/configurators    

       /dubbo/org.apache.dubbo.demo.DemoService/routers

     More than 3 path when the next node lamda expression if there is a change, will call registered org.apache.dubbo.registry.zookeeper.ZookeeperRegistry $$ Lambda $, execution method is ZookeeperRegistry.this.notify, will eventually adjust RegisterDirectory.notify ( URLs), the path into corresponding url, routing update, url cover configuration update, Invoker regenerate new configuration, configuration packets, delete old Invoker Mentioned above and other logic. Node path changes, performed twice configuration information coverage.

    

     Monitoring data changes: data path = / dubbo / config 

    data change, is a TreeCache Listener, and then register the child listens, each listener listens path of interest.

   There are two types:

   1.config data monitoring:

      demo-consumer.configurators                                         ->listener = RegistryDirectory$ConsumerConfigurationListener

     org.apache.dubbo.demo.DemoService.configurators             ->listener = RegistryDirectory$ReferenceConfigurationListener 

  2. router data monitoring:

     demo-consumer.condition-router                                      -->listener = AppRouter

    org.apache.dubbo.demo.DemoService.condition-router          -->listener = ServiceRouter

    demo-provider.tag-router                                                  -->listener = TagRouter

   

    configData changes are ultimately calling RegisterDirectory.refreshInvoker, but incoming url is Collections.emptyList. According to the code infer, is to save the data to a local zk, url using cacheUrls, call toInvoker method, internal zk will use the latest data, cacheUrl inside cover parameters, and then re-generate Invoker. The skip before the code, not get to know the logic,

   router data changes, the latest data will be retrieved zk, into a local save, it will become effective when follow-up service call.

  

 providers, configurators, routers change the path to a node, data config demo-consumer.configurators than the listener will be more change processing logic. But will perform configuration covering, invoker republished. 

   

IV Summary

    Consumer end start, mainly recorded before personal understanding more difficult place, a lot of places a little later.

    Dubbo Client Invoker start no record, this is more start Server side is almost the same, had the experience Server, and relatively easy to understand, Channel, ChannelHandler packaging is almost identical. netty Handler processes are internal Dubbo requestHandler, except that, client received eventually transferred to a method, server will reply modulation methods.

   In the consumer launch more than a few configuration changes is the provider subscription, routing, packet packaging. Configuration changes, listener passed relatively deep level, without records began relatively easy to confuse.

      

  Write more rough, if there are questions, welcome to put forward, discuss!

   

 

Guess you like

Origin www.cnblogs.com/keep-code/p/11133121.html