Environment
- Dubbo version: 2.7.3
- Operating System version: macOS 10.14.6
- Java version: 1.8
Steps to reproduce this issue
在我项目中,配置中心和注册中心都是使用zookeeper,而且是在一个集群上,只是 path 和对应的 username 和 password 不同,但是并未正常初始化两个不同的zk client。
项目启动时:
1、连接配置中心的地址,获取配置中心的配置信息
2、在初始化ReferenceBean和ServiceBean,会校验注册中心是否初始化
两者都通过 AbstractZookeeperTransporter#connect(URL url) 方法去连接zk
public abstract class AbstractZookeeperTransporter implements ZookeeperTransporter {
//缓存 zk client,key为zk地址
private final Map<String, ZookeeperClient> zookeeperClientMap = new ConcurrentHashMap<>();
@Override
public ZookeeperClient connect(URL url) {
ZookeeperClient zookeeperClient;
List<String> addressList = getURLBackupAddress(url);
// 这个地方会走缓存
if ((zookeeperClient = fetchAndUpdateZookeeperClientCache(addressList)) != null && zookeeperClient.isConnected()) {
logger.info("find valid zookeeper client from the cache for address: " + url);
return zookeeperClient;
}
。。。
}
ZookeeperClient fetchAndUpdateZookeeperClientCache(List<String> addressList) {
ZookeeperClient zookeeperClient = null;
for (String address : addressList) {
if ((zookeeperClient = zookeeperClientMap.get(address)) != null && zookeeperClient.isConnected()) {
break;
}
}
if (zookeeperClient != null && zookeeperClient.isConnected()) {
//将 zookeeperClient 放入 zookeeperClientMap 缓存中
writeToClientMap(addressList, zookeeperClient);
}
return zookeeperClient;
}
void writeToClientMap(List<String> addressList, ZookeeperClient zookeeperClient) {
for (String address : addressList) {
// 使用 address 作为key
zookeeperClientMap.put(address, zookeeperClient);
}
}
}
从上边可以看出,在初始化 配置中心的 zk client 后,就缓存到了 zookeeperClientMap 中。
当注册中心去初始化zk client 时,由于跟配置中心在一个集群上,所以 address相同,就会走缓存,返回 配置中心的 zk cliient。
总结:
如果配置中心和注册中心在一个集群上,zookeeperClientMap就不能使用address作为key。
解决方案:
URL信息(配置中心)

URL信息(注册中心)

通过上边两个图可以看出,配置中心 和 注册中心 传入的 URL信息里边的 path 是不相同的,将 zookeeperClientMap 的 key 使用 address + url.path 的方式生成,就可以解决这个问题
Environment
Steps to reproduce this issue
在我项目中,配置中心和注册中心都是使用zookeeper,而且是在一个集群上,只是 path 和对应的 username 和 password 不同,但是并未正常初始化两个不同的zk client。
项目启动时:
1、连接配置中心的地址,获取配置中心的配置信息
2、在初始化ReferenceBean和ServiceBean,会校验注册中心是否初始化
两者都通过 AbstractZookeeperTransporter#connect(URL url) 方法去连接zk
从上边可以看出,在初始化 配置中心的 zk client 后,就缓存到了 zookeeperClientMap 中。
当注册中心去初始化zk client 时,由于跟配置中心在一个集群上,所以 address相同,就会走缓存,返回 配置中心的 zk cliient。
总结:
如果配置中心和注册中心在一个集群上,zookeeperClientMap就不能使用address作为key。
解决方案:

URL信息(配置中心)
URL信息(注册中心)

通过上边两个图可以看出,配置中心 和 注册中心 传入的 URL信息里边的 path 是不相同的,将 zookeeperClientMap 的 key 使用 address + url.path 的方式生成,就可以解决这个问题