又踩到Dubbo的坑,但是这次我笑不出来( 二 )
我们先来看一下官方文档对RpcContext的介绍
文章插图
好了 , 那么我问你 , 下面这段代码 , love能输出什么?
@Servicepublic class AHelloServiceImpl implements AHelloService {@Referenceprivate BHelloService bHelloService;@Overridepublic String sayHello() throws Exception{RpcContext.getContext().setAttachment("我最爱的人是?","肥朝");bHelloService.sayHello();String love = RpcContext.getContext().getAttachment("我最爱的人是?");System.out.println("this is: " + love);Thread.sleep(10L);bHelloService.sayHello();return "欢迎关注微信公众号:肥朝";}}
我在图都圈得这么明显了 , 看得懂中文都知道 , 发起一次远程调用后 , 参数会被清空 , 下面肯定get不到的啦 。 但是其实是get得到的 , 不要问肥朝为什么都知道图是有问题的 , 还特意圈起来骗你 , 我只想让你知道社会险恶 。
源码细节阅读过源码 , 和对源码有细节深入思考 , 效果是很大不一样的 。
我们来看一下源码就知道了 。 文中说的会清楚 , 对应的代码是怎么样的呢?
文章插图
文章插图
如果作为正常的客户端调用 , 那么 , 在调用后确实是会删除的 。 但是如果你对源码细节足够熟悉你就会发现 , 在org.apache.dubbo.rpc.filter.ContextFilter这个类中 。
文章插图
文章插图
你不看代码直接听我说也行 , 这几段代码的意思是 , 在一个提供者的方法中 , canRemove会设置为false的 , 所以 , 他们在这个方法体远程调用中 , 是没办法清空RpcContext的 , 需要在整体调用完才会清空 。
我们再回顾一下案发现场
@Overridepublic String sayHello() throws Exception{bHelloService.sayHello();Thread.sleep(10L);bHelloService.sayHello();return "欢迎关注微信公众号:肥朝";}
从目前得到的信息很明显知道 , 第一次远程调用 , 和第二次远程调用 , 用的是同一个RpcContext,并且 , 在第二次远程调用的时候 。 这个RpcContext的内容 , 给人动了手脚了 。
那么 , 究竟是何人所为!我们随着镜头 , 再次深入源码!既然是RpcContext给人搞了 , 那么我们就从这里顺藤摸瓜,这里先省略肥朝的内心戏 , 我们来看重点 。 在RpcContext中发现一段可疑片段
public static void restoreContext(RpcContext oldContext) {LOCAL.set(oldContext);}
接着继续顺藤摸瓜,发现调用这段代码的逻辑是
/** * tmp context to use when the thread switch to Dubbo thread. */private RpcContext tmpContext;private RpcContext tmpServerContext;private BiConsumer
- 三星S21全面曝光,五年前挖的坑,自己出来了,国产手机进去了
- 分布式天花板?阿里百万架构师的ZK+Dubbo笔记,颠覆认知
- 我又踩坑了!如何为 HttpClient 请求设置 Content-Type 标头?
- dubbo实战之一:准备和初体验