老版本Dubbo的一个bug
线上有用户反应P 服务
页面时不时就报个错,后来发现都涉及I服务
的一个接口方法,这里暂且就叫F 接口
。只是时不时报错,那说明可能是某些参数会导致异常,于是我开始查看日志,看看是不是有什么特殊参数导致隐藏 bug 被发现。
结果是报错和不报错的请求参数都一样,那是不是多台机器上运行的代码不一致呢?于是我看了F 接口
的代码,发现最近没有迭代记录,而且所有机器上部署的代码均一致。
那有没有可能是环境问题?于是我上 Dubbo 控制台查看,发现 provider 和 consumer 都正常:
这个时候我开始有点懵逼了😅。
我又想到,如果是一直存在问题,那么不可能到今天才有用户反馈,所以还是跟近期的什么操作有关。于是我开始排查最早是什么时间出现的问题,发现是 10 月 10 日的 18:00:03
,又发现F 接口
所在的I服务
在10 月 10 日的 17:57:28
有过发布记录。
这下就有点奇怪了,就算I服务
所有机器同时发布,可能也就是报一会 no providers
错误啊,更不用说是滚动发布的,加上 dubbo 的 failover
不会一直报错的啊。
就在这时我看到了一个关键的错误信息:(之前只看到了 NPE 没具体位置):
问题直指DubboInvoker:109。
我们 dubbo的版本是(2.6.6),我拉下dubbo 代码发现这块的代码是这样的:
1 |
|
109 行报 NPE 莫非 client 是 null?带上猜测我开始看 client 是怎么来的,最终找到com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#getSharedClient
:
1 | private ExchangeClient getSharedClient(URL url) { |
又是一段平平无奇的代码😅,看到这里有用到锁,说明开发者考虑到这里可能会存在并发调用。我又看了下日志,10 月 10 日的 18:00:03
前后确实出现了并发调用的现象,难道是这里的并发控制有 bug?于是我开始思考各种场景,还真被我发现一种可能出问题的情况,下面我画了个图演示一下:
最后 序号 5 处返回了一个 null 的 client。
由于2.6.6 版本已经有点老,指不定这个问题已经有人提过,于是我到 github 一番搜索,结果找到了另外一个问题:https://github.com/apache/dubbo/issues/6444
这块dubbo 后面也迭代了好几次,已经搞不清楚了。
最后,重启大法好!