dubbo 2.7.7 配置 cluster 无效

发布于 2022-09-12 22:48:11 字数 883 浏览 23 评论 0

问题描述

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";
 }
}

已经做过的尝试

  1. debug 进去,看到向 zk 注册的 cluster 确实是 failfast,但是走的还是 failover 逻辑

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

城歌 2022-09-19 22:48:11

debug 了一下午,最后得出的结论是 dubbo 2.7.7 有 bug。论证过程如下。

先说 2.7.7 为什么不能按照我们的配置加载对应的 Cluster
再说 2.7.8 如何解决这个 bug 的。

2.7.7 流程

1、dubbo 如何根据你的配置文件加载对应的 Cluster?

源码位置:RegistryProtocol#doRefer()
image.png

Cluster 是一个接口,dubbo 会动态的生成Cluster$Adaptive 类。通过该类生成对应的 Cluster

@SPI(FailoverCluster.NAME)
public interface Cluster {
 <T> Invoker<T> join(Directory<T> directory) throws RpcException;
}

接下来把断点打到
AdaptiveClassCodeGenerator#generateMethod() AdaptiveClassCodeGenerator#generate()

dubbo 会帮我们生成以下类。

package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Cluster$Adaptive implements org.apache.dubbo.rpc.cluster.Cluster {
public org.apache.dubbo.rpc.Invoker join(org.apache.dubbo.rpc.cluster.Directory arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.cluster.Directory argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.cluster.Directory argument getUrl() == null");
org.apache.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("cluster", "failover");
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.cluster.Cluster) name from url (" + url.toString() + ") use keys([cluster])");
org.apache.dubbo.rpc.cluster.Cluster extension = (org.apache.dubbo.rpc.cluster.Cluster)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.cluster.Cluster.class).getExtension(extName);
return extension.join(arg0);
}
}

从生成的类代码会发现,会从 org.apache.dubbo.common.URL#getParameter(String key, String defaultValue) 方法中,获取 cluster 的配置。 这个方法最后从 URLparameters 属性中获取对应的值。

到这里,我们又有另外一个疑问。为什么从 parameters 中获取不到配置的 cluster 的值?如果能获取到我们配置的值,那就可以按照我们的配置来创建对应的 Cluster 了。 但是我们不是有配置吗?为什么会拿不到?dubbo 是如何填充 URL parameters 的值的?

2、dubbo 如何加载配置,并将配置放到 URL parameters 中?为什么 parameters 中没有我们配置的参数?

dubbo 的配置加载由 DubboBootstrap 负责。现在把断点打到 DubboBootstrap#initialize()
具体的配置加载,可以自行看下,这部分不是重点,你只要知道, dubbo 有把我们的配置加载出来即可。

加载完配置,现在就看下,dubbo 如何为我们生成 URL 的。
断点打到
ConfigValidationUtils#loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider)
image.png

在方法里面,dubbo 会从 AbstractInterfaceConfig(被加载的配置) 加载配置,以下是核心的代码。
image.png
问题就出在这里:这个加载配置的方法,并没有将 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) 方法的代码
image.png

Cluster 是一个动态加载的类。从 2.7.7 的流程中,可以知道,此时 URL 中的 parameters 参数没有 cluster。因此,加载出来的 Cluster 一定是默认的 FailoverCluster

在看下方法中, qs 局部变量,有我们配置的值。
image.png

2.7.8 生成 Cluster 主要逻辑

现在来看 2.7.8 如何解决这个 bug,其实挺简单的。下面贴上 2.7.8 的代码

image.png
image.png

多加一段代码,从 qs 中获取 cluster 的值,此时获取的 Cluster 就是对的了!

总结

太难了~ 刚学 dubbo 就遇到源码级别的 bug~,差点劝退了~。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文