什么是Dubbo的上下文信息?这里总结下本身的理解:java
上下文中存放的是当前 调用过程中所需的环境信息。全部的配置信息都将转换成URL的参数。RpcContext类就是Dubbo的上下文,可是它仅仅是一个ThreadLocal级别的 临时状态记录器,当接收到RPC请求或发起RPC请求时,RpcContext的状态都会变化。好比:A调用B、B再调用C的状况下。 B机器的RpcContext会有以下的状况发生:在B调用C以前,RpcContext记录的是A调B的信息,在B调用C以后,RpcContext记录的是B调C的信息。
好比:咱们想要获取到服务调用者的host相关信息,那么咱们能够在服务提供者中获取当前消费此服务的消费者的host信息,其代码以下所示:spring
// 获取调用方的host信息 String serverIP = RpcContext.getContext().getRemoteHost();
举个例子:用户在执行下单这个业务,最终确定会通过后台的订单服务、库存服务等服务。如今有个需求:在订单服务中,要明确知道这个订单是哪一个用户建立的。在库存服务中,要明确知道这个商品最终是用户的哪一个操做致使减小的。整个需求里面有个核心:就是要知道操做者是谁!假设项目用的是jwt技术来记录用户的状态,那么订单服务和库存服务就必需要知道这个jwt字符串,将jwt解码后,就能知道当前请求是由哪一个用户发起的。在这样的一个场景中,使用dubbo的隐式参数能够达到上述的目的。实现的伪代码以下所示:apache
RpcContext.getContext().setAttachment("jwt", "xxxxxxxxxxjwt字符串xxxxxxxx"); // dubbo rpc 调用库存服务:减小库存 warehouseService.decrement(); // dubbo rpc 调用订单服务:建立订单 orderService.create();
这里先总结下attachment在使用上的几个特色:框架
一、key名称不能以小驼峰命名,下游服务序列化后,会将key名称变成全小写(Dubbo 2.6.x版本,在2.7.x版本被修复了)分布式
二、隐式参数设置后,仅在第一次RPC请求生效,后续的RPC请求将没法获取到隐式参数学习
由于attachment有上述的两个特色,所以咱们很容易以下的两个错误:测试
易犯错误1 | 易犯错误2 |
---|---|
咱们在warehouseService.decrement() 的下游服务中能顺利的从attachment中获取jwt参数,而在orderService.create() 的下游服务中已经没法顺利的从attachment中获取jwt参数了 |
在本例中,添加到attachment中的key为jwt,是ok的。但若是咱们把key设置成大驼峰的命名方式,好比:userJwt。在通过Dubbo的一系列处理后,在warehouseService.decrement() 下游服务中的rpcContext对象中的attachment中的key已经变成了userjwt,已经没法获取到key为jwt的参数了。 |
针对错误1,咱们有三个实现方案,其对应的方案策略以下所示:编码
方案 | 优势 | 缺点 |
---|---|---|
方案1:在每一次发起RPC以前,都手动执行一次RpcContext.getContext().setAttachment("jwt", "xxxxxxxxxxjwt字符串xxxxxxxx"); 代码 |
能解决问题,但不是最优方案 | 增长编码的复杂度和代码的重复度。 |
方案2:使用spring的aop 的before机制,在执行rpc发起远程服务以前,先把jwt放入到attachment中 | 能解决问题 | dubbo的远程调用对象自己就很重量,如今再添加一层代理,不利于定位问题。 |
方案3:使用Dubbo的filter机制,在对指定远程服务添加一层filter,filter的逻辑就是将jwt放入到attachment中去 | 比较好的一种解决方案,充分利用到了Dubbo框架自身提供的filter扩展。这也是比较通用的解决方案,全链路追踪的traceId也是这么玩的。(推荐) | 代码阅读性不高,filter同aop同样,都是解耦的,不利于定位问题。 |
针对错误2,在不对源码进行扩展的状况下,最简单的方式就是修改key的命名方式,这里可使用两种方式:spa
方式1 | 参考Dubbo源码的org.apache.dubbo.common.constants.CommonConstants类中对添加到URL中的key的命令方式,多个单词用. 作区分 |
---|---|
方式2 | 单词与单词间使用自定义的符号作分隔,好比_,# 等符号。这种方式也能够区分于key是本身添加的仍是Dubbo框架自带的。 |