Skip to content

当配置中心和注册中心在一个zk集群上,zk为未正常初始化问题 #4991

@LookforAnswer

Description

@LookforAnswer
  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

Environment

  • Dubbo version: 2.7.3
  • Operating System version: macOS 10.14.6
  • Java version: 1.8

Steps to reproduce this issue

在我项目中,配置中心注册中心都是使用zookeeper,而且是在一个集群上,只是 path 和对应的 usernamepassword 不同,但是并未正常初始化两个不同的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信息(配置中心)
image

URL信息(注册中心)
image

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

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions