Dubbo 静态标签路由

Dubbo的架构如下图所示:图片来自http://dubbo.apache.org/zh-cn/docs/user/preface/architecture.html

dubbo-architecture.jpg

节点角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

调用关系说明
0.服务容器负责启动,加载,运行服务提供者。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

简单以代码为例描述一次调用的过程,首先当应用需要调用服务时,会通过invoke方法发起调用AbstractClusterInvoker:
此时会将RpcContext.getContext().getAttachments()的值set到invocation上,然后将invocation作为参数获取可以匹配到的Provider端提供的方法

    public Result invoke(final Invocation invocation) throws RpcException {
        checkWhetherDestroyed();

        // binding attachments into invocation.
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (contextAttachments != null && contextAttachments.size() != 0) {
            ((RpcInvocation) invocation).addAttachments(contextAttachments);
        }

        List<Invoker<T>> invokers = list(invocation);
        LoadBalance loadbalance = initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        return doInvoke(invocation, invokers, loadbalance);
    }

这里先跳过mock的部分,主要说明静态标签路由的部分,在获取服务方提供的List<Invoker>的方法中,Dubbo中的Router 负责从多个 Invoker 中按路由规则选出子集,也就是说通过 Directory 选出当前可用的服务提供者,然后再通过 Router 按规则过滤出服务提供者的子集。
针对TagRouter,在这次服务消费的请求中,invocation包含了tag的信息,如果提供方没有完全匹配的服务则进行服务降级,在提供方中查找没有tag的服务。
通过Router后才会进行负载均衡,以及Filter的拦截。

    public List<Invoker<T>> route(URL url, Invocation invocation) {
        List<Invoker<T>> finalInvokers = invokers;
        for (Router router : routers) {
            finalInvokers = router.route(finalInvokers, url, invocation);
        }
        return finalInvokers;
    }

所以采用基于Filter向RpcContext写入tag的方式是没有用的。

@Activate(group = Constants.CONSUMER)
public class FilterSpi implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        RpcContext.getContext().setAttachment(Constants.TAG_KEY,"tag1");
        Result result = invoker.invoke(invocation);
        return result;
    }
}

这里可以采用Spring的AOP的方式进行TAG_KEY的写入。或者不使用Duboo原生的TagRouter,自己定制一个新的TagRouter。

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Map<String, String> attachments = invocation.getAttachments();
        if (attachments != null) {
            attachments = new HashMap<>(attachments);
            attachments.remove(PATH_KEY);
            attachments.remove(INTERFACE_KEY);
            attachments.remove(GROUP_KEY);
            attachments.remove(VERSION_KEY);
            attachments.remove(DUBBO_VERSION_KEY);
            attachments.remove(TOKEN_KEY);
            attachments.remove(TIMEOUT_KEY);
            // Remove async property to avoid being passed to the following invoke chain.
            attachments.remove(ASYNC_KEY);
            attachments.remove(TAG_KEY);
            attachments.remove(FORCE_USE_TAG);
        }

PROVIDER在ContextFilter会执行attachments.remove(TAG_KEY);从而无法完成链路的调用,而我想将该tag值进行保留,所以不使用ContextFilter,并使用定制的Filter进行替换。

将定制的Filter用以下的方式进行配置


image.png
contextTag=xxx.xxx.xxx.TagContextFilter

并不再执行原生的ContextFilter

dubbo.provider.filter=-context
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 网络主播像人们展现自己漂亮,歌声动听,有文化,年轻,有钱,温柔等等优秀条件吸引着他们的粉丝,他们的粉丝想通过刷礼物...
    平安_75a8阅读 237评论 0赞 0
  • “王老师又被学生气哭了”,刘老师跟张老师说。 “感情太丰富”,张老师答到。 事情是这样的。 下午2:40上课。我走...
    飞舞的微辰阅读 345评论 1赞 1
  • 这是我人生中翻译的第一本外文的书,全书372页。 预计翻译时长为一年,今天列一个flag,待明年(2020年5月2...
    书情_cdaf阅读 423评论 1赞 2
  • 上一篇文章我们讲了如何通过二分查找进行搜索,今天这篇文章,我们介绍二分查找的高级版,即二叉查找树。二叉查找树主要解...
    航哥很帅阅读 1,095评论 0赞 1
  • 流水账一样的一天,早晨例行做早饭拍皂片,手疼的厉害,给宝宝们铲便便居然也用不上力气了~虽然知道不会有什么大事,可这...
    猫小埋阅读 230评论 0赞 0

友情链接更多精彩内容