ZooKeeper Cannot open channel to 2 at election address worker1/192.168.221.102:3888

项目场景

运行复制的ZooKeeper

问题描述

这是一个意外发现的问题,查了一下后发现并无大碍,但也要记录一下。

在三台机器上启动zk后jps进程正常,选举正常,但是查看日志却发现有报错。

image-20210514230900355

image-20210514231049378

详细错误:[myid:1] - WARN [QuorumConnectionThread-[myid=1]-2:QuorumCnxManager@401] - Cannot open channel to 3 at election address worker2/192.168.221.103:3888
java.net.ConnectException: Connection refused (Connection refused)

原因分析

起初我以为是防火墙、端口占用的原因,但我仔细一想不对啊,如果这种原因应该启动不来才对。在报了一堆警告后,又回归正常了

image-20210514231422554

说明这个问题在中途被自动解决了???

要搞懂它,首先得从这个3888端口说起,3888是我在conf/zoo.cfg中手动指定的,官网着详细说明

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

2888端口用来通信,准确的说是用来将follwer连接至leader的。而leader就是通过3888端口选举出来的。

所以最终这个问题的根源就是ZK的选举机制,有一篇文章写的很好,我直接拿过来

目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:

  • 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking(选举状态)。
  • 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
  • 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
  • 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
  • 服务器5启动,后面的逻辑同服务器4成为小弟。

由于我的启动脚本是用一个while循环遍历三台机器去启动ZK的,所以worker2的ZK启动要等待worker1的ZK启动,而worker1的ZK启动又要等待master的ZK启动。这就造成了当一个ZK先启动时(master),会不断连接其他未启动的两台机器进行选举,等待剩下的机器ZK全部开启,选举过程结束,错误自然就消失了,各自切换成follower或leader的状态。

解决方案

即使三台机器同时输入启动ZK的命令,也不能保证ZK的同时启动,所以这个警告不可避免,无需解决。

原文地址:https://www.cnblogs.com/pineapple-py/p/14773286.html