问题描述
dubbo 2.7.7 消费者、生产者配置 cluster 均无效。消费者调用超时时,依然走的是 failover 的逻辑。
基本描述
dubbo 版本 2.7.7
生产者:2 个
消费者配置
@DubboReference(version = "1.0.0", cluster = "failfast")
TestApiService testApiService;
@GetMapping("/sayHello")
public Object sayHello(String name) {
String hello = testApiService.sayHello(name);
return hello;
}生产者配置
@DubboService(version = "1.0.0", interfaceClass = TestApiService.class, cluster = "failfast")
public class TestApiServiceImpl implements TestApiService {
public String sayHello(String name) {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("我是 provider, 我被调用了");
return name + " say hello";
}
}已经做过的尝试
- debug 进去,看到向 zk 注册的 cluster 确实是 failfast,但是走的还是 failover 逻辑
debug 了一下午,最后得出的结论是 dubbo 2.7.7 有 bug。论证过程如下。
先说 2.7.7 为什么不能按照我们的配置加载对应的
Cluster,再说 2.7.8 如何解决这个 bug 的。
2.7.7 流程
1、dubbo 如何根据你的配置文件加载对应的 Cluster?
源码位置:

RegistryProtocol#doRefer()Cluster是一个接口,dubbo 会动态的生成Cluster$Adaptive类。通过该类生成对应的Cluster接下来把断点打到
AdaptiveClassCodeGenerator#generateMethod()AdaptiveClassCodeGenerator#generate()dubbo 会帮我们生成以下类。
从生成的类代码会发现,会从
org.apache.dubbo.common.URL#getParameter(String key, String defaultValue)方法中,获取cluster的配置。 这个方法最后从URL的parameters属性中获取对应的值。到这里,我们又有另外一个疑问。为什么从
parameters中获取不到配置的cluster的值?如果能获取到我们配置的值,那就可以按照我们的配置来创建对应的Cluster了。 但是我们不是有配置吗?为什么会拿不到?dubbo 是如何填充URL parameters的值的?2、dubbo 如何加载配置,并将配置放到 URL parameters 中?为什么 parameters 中没有我们配置的参数?
dubbo 的配置加载由
DubboBootstrap负责。现在把断点打到DubboBootstrap#initialize()上具体的配置加载,可以自行看下,这部分不是重点,你只要知道, dubbo 有把我们的配置加载出来即可。
加载完配置,现在就看下,dubbo 如何为我们生成 URL 的。

断点打到
ConfigValidationUtils#loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider)在方法里面,dubbo 会从

AbstractInterfaceConfig(被加载的配置) 加载配置,以下是核心的代码。问题就出在这里:这个加载配置的方法,并没有将
AbstractInterfaceConfig中的 cluster 放到 URL 中。因此,导致我们在创建对应的
Cluster时,拿到的是默认的failover。从我个人理解来看,这应该是 bug \~\~\~。当然可能不对,欢迎大佬指正
2.7.8 流程
2.7.8 的流程 整体和 2.7.7 一样。主要是获取
Cluster的方法方法不大一样。2.7.7 生成 Cluster 主要逻辑
下图是 2.7.7

RegistryProtocol#refer(Class<T> type, URL url)方法的代码Cluster是一个动态加载的类。从 2.7.7 的流程中,可以知道,此时 URL 中的parameters参数没有cluster。因此,加载出来的Cluster一定是默认的FailoverCluster。在看下方法中, qs 局部变量,有我们配置的值。

2.7.8 生成 Cluster 主要逻辑
现在来看 2.7.8 如何解决这个 bug,其实挺简单的。下面贴上 2.7.8 的代码
多加一段代码,从 qs 中获取
cluster的值,此时获取的Cluster就是对的了!总结
太难了~ 刚学 dubbo 就遇到源码级别的 bug
~,差点劝退了~。