An overview of Dubbo routing mechanism

In the previous section, we mainly explained how to dynamically modify parameters using dubbo-admin. This section will focus on another implementation detail in cluster implementation: routing mechanism, the main purpose of which is to refresh service providers from all known service providers according to routing rules when making service calls.

1. Overview of Dubbo routing mechanism

The following is from official documents:

Above is the basic knowledge of Dubbo routing mechanism, and then from the source point of view to analyze its implementation principle.

2. Router Related Class Diagram

  1. Router:dubbo Routing Interface Class URL getUrl(): Get the route configuration URL. << T> List < Invoker < T > route (List < Invoker < T > invokers, URL url, Invocation invocation): Returns a regular service caller based on routing rules.
  2. ConditionRouter: Conditional routing rule.
  3. ScriptRouter: A script routing rule (JavaScript).

2.1 How to add routing rules

You can manage the background through dubbo-admin to dynamically add routing rules with the interface shown in the diagram:

After clicking Save, describe a routing rule using a URL, store it in the registry ${service}/routers directory, and notify the relevant subscribers (service consumers [callers]). The method invoked is the RegistryDirecotry#notify method with the following fragments:

// routers
if (routerUrls != null &amp;&amp; !routerUrls.isEmpty()) {  // @1
     List<router> routers = toRouters(routerUrls);     // @2
     if (routers != null) { // null - do nothing           
          setRouters(routers);                                        // @3
      }
}

Code @1 : If routerUrls are not empty, some routing rules have been added or deleted in the catalog=routers directory of the registry, and finally there are routing rules. Code @2: Converts a routing rule URL to an implementation class that implements a Router-like interface, such as a conditional routing rule, a script routing rule concrete implementation class. Code @3: Override the RegistroyDirectory#routers property with the existing routing rule implementation classes, which will take effect the next time the service is invoked.

Let's look at the implementation of the toRouter method:

RegistryDirectory#toRouters

private List<router> toRouters(List<url> urls) {
        List<router> routers = new ArrayList<router>();
        if (urls == null || urls.isEmpty()) {
            return routers;
        }
        if (urls != null &amp;&amp; !urls.isEmpty()) {
            for (URL url : urls) {
                if (Constants.EMPTY_PROTOCOL.equals(url.getProtocol())) {
                    continue;
                }
                String routerType = url.getParameter(Constants.ROUTER_KEY);
                if (routerType != null &amp;&amp; routerType.length() &gt; 0) {
                    url = url.setProtocol(routerType);
                }
                try {
                    Router router = routerFactory.getRouter(url);
                    if (!routers.contains(router))
                        routers.add(router);
                } catch (Throwable t) {
                    logger.error("convert router url to router error, url: " + url, t);
                }
            }
        }
        return routers;
    }

Method implementation is simple, based on protocol header condition://or script://Build a specific routing rule implementation class. From the above two methods, it can be seen that when the master-from-center routing configuration changes, the RegistryDirectory's List< Router> Routers property is rebuilt, so when is this property used?

AbstractDirectory#list

public List<invoker<t>&gt; list(Invocation invocation) throws RpcException {
        if (destroyed) {
            throw new RpcException("Directory already destroyed .url: " + getUrl());
        }
        List<invoker<t>&gt; invokers = doList(invocation);
        List<router> localRouters = this.routers; // local reference
        if (localRouters != null &amp;&amp; !localRouters.isEmpty()) {
            for (Router router : localRouters) {
                try {
                    if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
                        invokers = router.route(invokers, getConsumerUrl(), invocation);
                    }
                } catch (Throwable t) {
                    logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
                }
            }
        }
        return invokers;
    }

When getting List < Invoker > through RegistryDirector, all Invoker lists will be routed and filtered, and then returned to Invoker that meets the routing rules. This article does not believe in analyzing how Dubbo filters according to the configured conditional routing rules, script routing rules. If you are interested, you can pay attention to: ConditionRouter, ScriptRouter.

Author's introduction: Dingwei, author of Insider of RocketMQ Technology, RocketMQ community evangelist, Public Number: Middleware Circle of Interest Maintainer, Source Analysis Java Collection, Java Concurrent Packaging (JUC), Netty, Mycat, Dubbo, RocketMQ, Mybatis and other source columns have been published successively.You can click on the link: Middleware Knowledge Planet To discuss high concurrency, distributed service architecture and exchange source code.

</router></invoker<t></invoker<t></router></router></url></router></router>

Keywords: Programming Dubbo Java Javascript Netty

Added by spider.nick on Sun, 05 Jan 2020 13:41:28 +0200