你好呀,我是why。
前两天在 Git 上闲逛的时候又不知不觉逛到 Dubbo 那里去了。
看了一下最近一个月的数据,社区活跃度还是很高的:
然后看了一下最新的 issue,大家提问都很积极。
其中看到了这样的一个 issue,发现有点意思:
于是写下这篇文章给你分享一下这个 BUG 和 BUG 背后的故事。
放心,就算你完全不懂 Dubbo,也不影响你了解这个 BUG。
先说一下,下文中提到的 Dubbo 代码,没有特别说明的地方,都是我从 git 上拉下来的 Master 分支上的代码
啥 BUG 啊?
先给你描述一个这个 BUG 是啥样的。
其实就是这个 issue 的作者写出来的:Dubbo 框架里面的 Filter 排序过程有问题,即使按照框架要求写好规则后,最终生成的 Filter 链并不是我们想要的。
那么完全不懂 Dubbo 的朋友可能就遇到了第一个问题:啥是 Filter 呢?
其实就是一个过滤器而已,和 web 服务里面过滤器在概念上没啥两样。而 Dubbo 有非常多的 Filter,这些 Filter 共同组成了一个 Filter 调用链。
引用官网上的一个调用链路图,在 Filter 的地方我框起来了:
可以看到 Filter 是 Dubbo 框架的一个非常核心的组成部分,很多很多的功能都是从 Filter 扩展出来的。
你要是还不明白也没关系,你只要知道有这样的一个 Filter 调用链就行了,链上的 Filter 各司其职,各干各的事儿。
好的,那么现在需求来了:
我现在要求链上的 Filter 的执行顺序是我能控制的,即我定义 Filter 的时候你得给我留个地方设置它的优先级。
听起来是很简单的一个需求,对吧?
我直接给你留个口子,让你输入 order 参数,不输入给个默认值,然后组装 Filter 链的时候根据 Order 排个序。
不是我吹牛,十分钟就能写完,中间还带着三分钟的摸鱼。
但是,就这么个需求出 BUG 了。
具体啥现象呢?
我这里把项目拉下来,基于官方的测试用例,改巴改巴,给你演示一下这个 BUG 的体现是啥。
在 Dubbo 里面有这样的一个注解:
org.apache.dubbo.common.extension.Activate
这里的 Order 就是做排序用的。简单演示一下,你看我现在有 5 个 Filter:
排序规则是 Order 越小的越先执行,那么这个 Filter 链的执行顺序应该是这样的:
Filter4 -> Filter3 -> Filter2 -> Filter1 -> Filter5
搞个测试案例,我们验证一下:
符合预期,没有任何毛病。
另外说明一下,官方的关于 Filter 的测试用例在这里,你有兴趣,源码拉下来就可以看:
org.apache.dubbo.common.extension.support.ActivateComparatorTest#testActivateComparator
不管是官方的案例,还是我自己写的案例,其中最关键的排序功能是这一行代码实现的:
Collections.sort(filters, ActivateComparator.COMPARATOR)
而这一行代码里面最关键的就是 ActivateComparator.COMPARATOR
这个东西。
这个东西就是 BUG 之源,不慌,等下再说。
那么为什么说它有 BUG 呢?
前面演示了正常的情况下,是符合预期的。
但是你看 Activate
注解,里面还有这样的两个东西:
before、after,含义是指定 Filter A 在 Filter B 之前或者之后执行。
但是被打上了 @Deprecated
注解,字段说明上也备注了:
Deprecated since 2.7.0
2.7.0 之后被废除。
那么就有点意思了,为啥被废除?
来,看个例子,还是刚刚的那个测试用例。
我就稍微的这么一改:
@Activate(before = "_2") public class Filter5 implements Filter0{ }
改动点就是在 Filter5 上配置了:
@Activate(before = "_2")
含义就是 Filter5 在 “_2” 之前执行。
“_2” 是啥?
就是 Filter2 的一个映射而已:
那么问题就来了,作为一个正常的程序猿,自信的对 Filter5 进行了这个改动之后,他内心的想法一定是想要把这样的 Filter 链:
Filter4 -> Filter3 -> Filter2 -> Filter1 -> Filter5
修改为这样:(Filter5 在 Filter2 之前执行):
Filter4 -> Filter3 -> Filter5 -> Filter2 -> Filter1
那么实际情况是怎样的呢?
来跑一把:
咋回事?这不是我预期的执行链啊?
是的,这就是 BUG 的表现。