迁移Zookeeper时Dubbo是否会注册到新的ZK上

为了说明问题, 这里描述一下场景.

应用配置的ZK地址是zk.infuq.com, 通过DNS解析的IP是192.168.0.1, 因此应用连接到了ZK1

在这里插入图片描述

然后把DNS的映射关系改成如下图所示,让zk.infuq.com解析成ZK2的IP(192.168.0.2), 先关闭ZK1的服务(或者禁用2181端口的出入流量)过了1分钟再开启服务(目的就是让ZK1和应用断开连接),根据应用(Dubbo应用)的重连机制, 最后应用连接注册到ZK2上.
在这里插入图片描述
然而, 这样操作之后, 应用真的可以连接到ZK2上吗?

先说下答案, 根据应用服务器配置的zookeeper版本不同,应用服务器可能还会连接到ZK1上,也可能会连接到ZK2上.

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>

如果使用的版本是3.4.9, 那么应用服务器会连接到ZK1上.

Dubbo服务在启动的过程中,会连接ZK,其中会进入org.apache.zookeeper.client.StaticHostProvider#StaticHostProvider代码,实例化StaticHostProvider.

public StaticHostProvider(Collection<InetSocketAddress> serverAddresses) throws UnknownHostException {
    for (InetSocketAddress address : serverAddresses) {
        // ia == null
        InetAddress ia = address.getAddress();
        // 解析IP
        InetAddress resolvedAddresses[] = InetAddress.getAllByName((ia!=null) ? ia.getHostAddress(): address.getHostName());
        for (InetAddress resolvedAddress : resolvedAddresses) {
            if (resolvedAddress.toString().startsWith("/") 
                && resolvedAddress.getAddress() != null) {
                this.serverAddresses.add(
                    new InetSocketAddress(InetAddress.getByAddress(
                        address.getHostName(),
                        resolvedAddress.getAddress()), 
                                          address.getPort()));
            } else {
                this.serverAddresses.add(new InetSocketAddress(resolvedAddress.getHostAddress(), address.getPort()));
            }  
        }
    }

    if (this.serverAddresses.isEmpty()) {
        throw new IllegalArgumentException(
            "A HostProvider may not be empty!");
    }
    Collections.shuffle(this.serverAddresses);
}

它会​根据域名解析IP, 拿到配置的zk.infuq.com域名,解析IP(192.168.0.1).​

解析出来的IP(192.168.0.1)最后封装成InetSocketAddress并放到serverAddresses集合中.

在这里插入图片描述也就是说,​不管是首次连接ZK还是重连ZK,都是从serverAddresses集合中取出地址进行连接ZK,而不会再重新解析IP.

如果是3.4.13版本

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.13</version>
</dependency>

这个版本的逻辑是,​如果需要连接ZK,都是调用下面的next方法获取地址. 而它每次都会解析IP,一旦DNS有变动,那么就会解析到新的IP地址.

public InetSocketAddress next(long spinDelay) {
    ...

    InetSocketAddress curAddr = serverAddresses.get(currentIndex);
    try {
        // curHostString是域名,例如zk.infuq.com
        String curHostString = getHostString(curAddr);
        // 解析IP
        List<InetAddress> resolvedAddresses = new ArrayList<InetAddress>(Arrays.asList(this.resolver.getAllByName(curHostString)));
        if (resolvedAddresses.isEmpty()) {
            return curAddr;
        }
        Collections.shuffle(resolvedAddresses);
        // 返回地址
        return new InetSocketAddress(resolvedAddresses.get(0), curAddr.getPort());
    } catch (UnknownHostException e) {
        return curAddr;
    }
}

所以,最后结论如下图所示,根据不同的Zookeeper版本,应用会连接不同的ZK.

在这里插入图片描述


个人站点
语雀

公众号

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值