遇到的问题:
对一个多节点的集群的某个节点重启后,该节点无法正常加入ZK集群。
具体现象
bin/zkServer.sh status
JMX enabled by default
......
Error contacting service. It is probably not running.
该节点的 zk进程处于运行状态,日志持续出现此类信息:
“Have smaller server identifier, so dropping the connections: (3,2)”;
“Notification timeout: 60000”
临时解决方案
重启其他节点的zk进程,则该节点能正常加入zk集群。
根本原因
zookeeper 某版本的bug:https://issues.apache.org/jira/browse/ZOOKEEPER-2186

Zookeeper启动时,会创建一个Listener子线程,该子线程创建绑定端口为选举端口的SocketServer,该SocketServer监听ZK集群其他peer节点socket连接,接收并进行处理。
public class Listener extends Thread {
volatile ServerSocket ss = null;
/**
* Sleeps on accept().
*/
@Override
public void run() {
int numRetries = 0;
InetSocketAddress addr;
while((!shutdown) && (numRetries < 3)){
try {
ss = new ServerSocket();
ss.setReuseAddress(true);
if (self.getQuorumListenOnAllIPs()) {
int port = self.quorumPeers.get(self.getId()).electionAddr.getPort();
addr = new InetSocketAddress(port);
} else {
addr = self.quorumPeers.get(self.getId()).electionAddr;
}
LOG.info("My election bind port: " + addr.toString());
setName(self.quorumPeers.get(self.getId()).electionAddr
.toString());
ss.bind(addr);
while (!shutdown) {
Socket client = ss.accept();
setSockOpts(client);
LOG.info("Received connection request "
+ client.getRemoteSocketAddress());
receiveConnection(client);
numRetries = 0;
}
} catch (IOException e) {
LOG.error("Exception while listening", e);
numRetries++;
try {
ss.close();
Thread.sleep(1000);
} catch (IOException ie) {

博客讨论了Zookeeper集群中一个节点重启后无法正常加入的问题,具体表现为Listener线程无法处理其他节点的连接请求。问题的根本原因是Zookeeper的某个版本存在bug,导致在接收socket连接时出现错误。修复方案是更新到修复此问题的新版本,以避免因接收不合理长度的数据导致内存溢出。此外,通过示例代码展示了Socket客户端如何触发类似问题,以及修复代码如何防止此类异常。
最低0.47元/天 解锁文章
2553

被折叠的 条评论
为什么被折叠?



