SpringBoot整合Dubbo3.x关于curator和zookeeper版本选型的思
⼀、Dubbo2 or Dubbo3?
我给出的观点是选择Dubbo3,原因有⼆:
1. 在 Dubbo 3.0 版本向下兼容⽼版本 Dubbo
2.5、2.6、2.7;
java dubbo2. Dubbo
3.0 的带来了许多的新特性,⽤户可以按需进⾏升级;
参考⾃Apache官⽅⽂档
在 SpringBoot 整合 Dubbo 时,如果引⽤依赖dubbo-spring-boot-starter,会⾃动依赖dubbo,且版本号⼀致:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>
当然,如果选择直接引⽤ Dubbo :
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.1</version>
</dependency>
⼆、Zookeeper&curator or Zookeeper&zkclient
Dubbo 常⽤的注册中⼼有 Nacos、ZooKeeper、Multicast、Redis、Simple。本⽂主要讨论 ZooKeeper 作为 Dubbo 的注册中⼼时,版本的选择。
Dubbo ⽀持 zkclient 和 curator 两种 Zookeeper 客户端实现。
注意:在2.7.x的版本中已经移除了zkclient的实现,如果要使⽤zkclient客户端,需要⾃⾏拓展
参考⾃ Apache Dubbo 官⽹
curator ⽐ zkclient 更加通⽤,还有许多现成好⽤的API,且 curator 有相对完善的⽂档。就像 Curator 的⼝号⼀样:
所以不考虑 zkclient,选⽤ curator。
三、Curator 和 Zookeeper 的兼容问题
ZooKeeper 3.4.x 已经⾛到头了。因此,最新版本的Curator取消了对它的⽀持。如果你想使⽤ Zookeeper 3.4.x 您应该锁定到 Curator 版本4.2.x。
Curator 4.2.x 以软兼容模式⽀持 ZooKeeper 3.4.x 集成。要使⽤此模式,在向依赖关系管理⼯具添加Curator时,必须排除ZooKeeper。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
<exclusions>
<exclusion>
<groupId>keeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
翻译⾃
3.1 兼容⽼服务器ZooKeeper3.
4.x的版本选型
如果 ZooKeeper 服务器选型为 3.4.x 时,采⽤以下选型(主要针对 ZooKeeper 服务器集使⽤较低版本的情况):
Dubbo 3.0.1 & Curator 4.2.0 & Zookeeper 3.4.x
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
<exclusions>
<exclusion>
<groupId>keeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>keeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
</dependencies>
⼀张表来说明需要要到的Curator相关包:
GroupID ArtifactID描述
org.apache.curator curator-recipes All of the recipes. 该 artifact 依赖 curator-framework 和 curator-client
org.apache.curator curator-framework Curator框架 high-level API。建⽴在 curator-client 之上。
org.apache.curator curator-client ZK发⾏版中ZooKeeper类的替代品。
org.apache.curator curator-x-discovery基于Curator框架的服务发现实现
翻译⾃Curator官⽅⽂档
zookeeper 中排除了⽇志相关的三个包,就可以让 ZooKeeper 的⽇志框架保持和整体⽇志框架⼀致,但是slf4j-api是不可缺少的⽇志门⾯。
同样地,排除 curator-client 中的slf4j-api包,也是为了让其⽇志框架和整体⽇志框架⼀致。
3.2 新搭ZooKeeper环境
针对新搭 ZooKeeper 的情况,可以采⽤更新的版本:
Dubbo 3.0.5 & Curator 5.2.0 & Zookeeper 3.6.3 ,选择 ZooKeeper 3.6.3 是因为 curator-client 5.2.0 的其中⼀个依赖就是 zookeeper 3.6.3(Dubbo 3.0.2+ 都可以,但是 Dubbo 3.0.1 有点兼容问题)
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
四、关于选型新版本的⼀点⼩问题
4.1 问题描述和解决⽅案
我使⽤,
但是我在启动Dubbo应⽤服务时出现以下错误:
我查了很久的源码,才弄清楚原因。解决⽅案是在 hosts 中给 zoo1,zoo2,zoo3 配置 ip,例如在 hosts ⽂件末尾追加
10.24.99.61 zoo1
10.24.99.61 zoo2
10.24.99.61 zoo3
10.24.99.61则是我⽤ ipconfig 命令(Windows系统)查询到⼀个本机Ipv4地址。
4.2 源码解析
⾸先,如果你⽤的 Curator 5.2.0,那么使⽤的是Curator5ZookeeperClient,如果你⽤的是 Curator 4.2.0,使⽤的则是CuratorZookeeperClient,截取了部分核⼼代码:
把断点放在client.start(),并继续跟踪代码,代码会进⼊CuratorFrameworkImpl的start()⽅法,其中有⼀段代码
if ( ensembleTracker != null )
{
ensembleTracker.start();
}
这段代码,如果使⽤ ZooKeeper 3.4.x 时,ensembleTracker等于null;相反地,使⽤ ZooKeeper 3.6.3 则不为 null,原因是CuratorFrameworkImpl构造函数中的这段代码:
ensembleTracker = zk34CompatibilityMode ? null : new EnsembleTracker(this, EnsembleProvider());
⾄于 zk34CompatibilityMode 则是根据org.apache.curator.utils.Compatibility判断的(这⾥就不展开了,原来就是反射查看keeper.admin.ZooKeeperAdmin是否能到来判断的)。
然后,再来看EnsembleTracker的start()⽅法
// org.apache.curator.framework.imps.EnsembleTracker
public void start() throws Exception
{
Preconditions.checkState(statepareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
reset();
}
继续跟踪EnsembleTracker的reset()⽅法
private void reset() throws Exception
{
if ( (State() == CuratorFrameworkState.STARTED) && (() == State.STARTED) )
{
BackgroundCallback backgroundCallback = new BackgroundCallback()
{
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
{
outstanding.decrementAndGet();
if ( (Type() == CuratorEventType.GET_CONFIG) && (ResultCode() == KeeperException.Code.OK.intValue()) )        {
Data()); // 这⾥是重点
}
}
};
outstanding.incrementAndGet();
try
{
outstanding.incrementAndGet();  // finally block will decrement
}
finally
{
outstanding.decrementAndGet();
}
}
}
断点放在processConfigData上,并进⼊该⽅法,继续跟踪:
private void processConfigData(byte[] data) throws Exception
{
Properties properties = new Properties();
properties.load(new ByteArrayInputStream(data));
log.info("New config event received: {}", properties);
if (!properties.isEmpty())
{
QuorumMaj newConfig = new QuorumMaj(properties); // 本质产⽣异常的⽅法
String connectionString = configToConnectionString(newConfig); // 抛出异常的⽅法
if (im().length() > 0)
{
currentConfig.set(newConfig);
ensembleProvider.setConnectionString(connectionString);
}
else
{
log.debug("Invalid config event received: {}", properties);
}
}
else
{
log.debug("Ignoring new config as it is empty");
}
}
抛出异常的是configToConnectionString调⽤hostAddress = HostAddress(server);:
因为addr等于 null 才导致的错误,但是这不是“第⼀案发现场”,真正发⽣问题是在QuorumMaj newConfig = new QuorumMaj(properties);之中:
将 server.1=zoo1:2888:3888:participant;0.0.0.0:2181 server.2=zoo2:2888:3888:participant;0.0.0.0:2182
server.3=zoo3:2888:3888:participant;0.0.0.0:2183 逐⼀解析为QuorumServer对象,其中调⽤InetSocketAddress构造函数时:
当 zoo1 不到对应的 ip 时,addr 就会为null。这就是问题的原因。所以配置⼀下本地 hosts 就能搞定了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。