又踩到Dubbo的坑,但是这次我笑不出来
作 者:肥朝
原文链接:;utm_medium=referral
前言直入主题 , 线上应用发现 , 偶发性出现如下异常日志 。
文章插图
文章插图
当然由于线上具体异常包含信息量过大 , 秉承让肥朝的粉丝没有难调试的代码的原则 , 我特意抽取了一个复现的demo放在了git,让你不在现场 , 一样享受到排查的快乐!但是最近 , 太多假粉伸手党拿到地址就跑 , 因此我把地址藏在本文某个角落 , 因此认真看文的才能找到!(重点)
由于工作性质的原因 , 上班时间根本抽不出时间做其他事 , 修bug , 都只能下班时间来做 , 因此周六就到公司搬砖了 。
文章插图
什么是ConcurrentModificationException?中文意思就是 , 并发修改异常 。 也就是我们常说的fail-fast(快速失败) 。 当然肥朝更认为 , 快速失败是一种思想 , 比如Spring会在启动的时候做大量的检查 , 什么bean找不到 , 依赖注入错误等等 , 都会把一些显而易见的错误检查出来 , 防止在项目跑着跑着期间再失败 , 也就是提前检查 。 无论是业务开发 , 还是基础组件开发 , 亦或是生活中 , 这个思想都是可以用到的 。
那么 , 言归正传 , 这个异常到底什么意思啊 。 简单说就是 , 当一个集合在遍历的时候 , 他的元素也正在被修改 。 刚学java那会 , 我们边遍历边删除就会出现这个异常 。 ConcurrentModificationException的原理这些网上太多 , 肥朝就暂且不提 。 那么我们来看下异常栈 。
文章插图
文章插图
好了 , 我们已经找到了RpcContext.getContext().getObjectAttachments()正在遍历 。 那么 , 只要找到谁在修改他就行了啊 , 就这?
文章插图
难点分析很明显 , 这里面并不存在遍历的同时修改元素 , Dubbo的代码还不至于有这个明显的bug 。 出现ConcurrentModificationException , 就有可能是 , A线程在遍历 , B线程在修改 。
但是肥朝 , 你说了这么多 , 我还是没发现这个问题有什么难的啊!
这个问题难点主要在于 , 在Dubbo里面 , RpcContext是对应一个线程的 , 你可以简单理解为ThreadLocal的增强版 。 也就是说 , A线程拿出来的 , 和B线程拿出来的RpcContext都不是同一个 , 何来并发修改同一个之说?当然官方文档给了我一个启示 。
文章插图
会不会有同学在线程开启前拿到RpcContext,然后在新线程中 , 做set操作(图中的get操作是没有问题的) 。
于是 , 似乎豁然开朗的我 , 顺着这条线索 , 周六加了一天班 , 把代码翻了个遍 , 最后发现没有找到 。
索然无味还是柳暗花明?【又踩到Dubbo的坑,但是这次我笑不出来】并发这东西 , 要么不出问题 , 一旦出问题都是很难找 。 观察了线上日志 , 重现概率很小 , 就一小段日志 , 并且业务方很忙 , 也没时间配合你查问题 。 于是只能顺着源码 , 把Dubbo的整个请求到响应的过程在脑海中快速过几遍 , 看看哪个环节有可能出问题 , 做了无数的假设 。 随着一次次的假设失败 , 在即将身体索然无味之际 , 还真发现了一些蛛丝马迹!(注意 , 本文所用到的 , 都是dubbo2.7.6)
我们先来看一下官方文档对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得到的 , 不要问肥朝为什么都知道图是有问题的 , 还特意圈起来骗你 , 我只想让你知道社会险恶 。
- 王文鉴|从工人到千亿掌门人,征服华为三星,只因他36年只坚持做一件事
- 手机|这个超强App,让手机快3倍,流畅到起飞
- 巅峰|realme巅峰之作:120Hz+陶瓷机身+5000mAh 做到了颜值与性能并存
- 现货供应|卢伟冰说到做到!120Hz+一亿像素,狂销30万首销现货供应
- 打响|拼多多打响双12首枪,iPhone12降到“mini价”,苹果11再见
- 深度|iPhone12到底值得买吗 深度体验一周我发现了这些
- 不到|苹果赚了多少?iPhone12成本不到2500元,华为和小米的利润呢?
- 星期一|亚马逊:黑五与网络星期一期间 第三方卖家销售额达到48亿美元
- 权属|从数据悖论到权属确认,数据共享进路所在
- 月入|一上网,感觉网上每个人都是月入过万,到底是错觉还是你out了?