dubbo的路由规则

因为项目部署分需要灰度发布,涉及到公用依赖需要根据版本号来路由到不同机器。

使用了dubbo的keeper项目作为后台管理来新增路由规则,翻看dubbo源码,

 

发现dubbo使用了代理,代理会做的一件事就是使用路由规则

//AbstractDirectory 类
public List> list(Invocation invocation) throws RpcException {
        if (this.destroyed) {
            throw new RpcException("Directory already destroyed .url: " + this.getUrl());
        } else {
            List> invokers = this.doList(invocation);
            List localRouters = this.routers;
            if (localRouters != null && !localRouters.isEmpty()) {
                Iterator var4 = localRouters.iterator();

                while(var4.hasNext()) {
                    Router router = (Router)var4.next();

                    try {
//这行代码可以看出,如果需要每次调用都使用规则的话,需要在提供服务那边加上
//@Service(parameters = {"runtime", "true"}) 这个注解
                        if (router.getUrl() == null || router.getUrl().getParameter("runtime", false)) {
                            invokers = router.route(invokers, this.getConsumerUrl(), invocation);
                        }
                    } catch (Throwable var7) {
                        logger.error("Failed to execute router: " + this.getUrl() + ", cause: " + var7.getMessage(), var7);
                    }
                }
            }

            return invokers;
        }
    }

目前存在消费者A调用服务B,消费者C调用服务D。

现在存在的问题是,如果服务B挂了,则根据dubbo的服务降级等默认策略,此时消费者A会调用服务D,此时就

没有起到路由的作用。

继续看源码:

//ConditionRouter 类
public  List> route(List> invokers, URL url, Invocation invocation) throws RpcException {
        if (invokers != null && !invokers.isEmpty()) {
            try {
                if (!this.matchWhen(url, invocation)) {
                    return invokers;
                }

                List> result = new ArrayList();
                if (this.thenCondition == null) {
                    logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
                    return result;
                }

                Iterator var5 = invokers.iterator();

                while(var5.hasNext()) {
                    Invoker invoker = (Invoker)var5.next();
                    if (this.matchThen(invoker.getUrl(), url)) {
                        result.add(invoker);
                    }
                }

                if (!result.isEmpty()) {
                    return result;
                }

                //此时如果force = true的话,而此时result是为空的,可以发现上次调用router的地方会抛出异常,导致本次调用失败,然后可以通过报警,告知服务挂了,而不是调用被隔离的服务D
                if (this.force) {
                    logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded("rule"));
                    return result;
                }
            } catch (Throwable var7) {
                logger.error("Failed to execute condition router rule: " + this.getUrl() + ", invokers: " + invokers + ", cause: " + var7.getMessage(), var7);
            }

            return invokers;
        } else {
            return invokers;
        }
    }

但是发现在keeper的配置地方没有配置force=true的地方,因此只能侵入代码,在创建路由规则的时候,令force=true

 

 

 

你可能感兴趣的:(dubbo源码)