前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >迁移Zookeeper时Dubbo是否会注册到新的ZK上

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

作者头像
书唐瑞
发布2022-06-02 14:12:16
5360
发布2022-06-02 14:12:16
举报
文章被收录于专栏:Netty历险记

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

应用配置的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上.

代码语言:javascript
复制
<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.

代码语言:javascript
复制
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版本

代码语言:javascript
复制
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.13</version>
</dependency>

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

代码语言:javascript
复制
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.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Netty历险记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档