前言:
Zookeeper在我们的实际使用中,都是以集群模式来对外提供服务。
在客户端的使用中,写入集群所有节点的ip:port信息,客户端启动后便会随机选择一个Zookeeper server节点创建长连接。
如果当前连接的Zookeeper server节点网络异常,当前长连接便会断掉重连。
本文主要就来看下Zookeeper客户端是如何检测连接断掉,并自动做重连动作的。
有关于Zookeeper客户端状态的相关信息可以参考笔者另一篇博客: zookeeper客户端会话状态分析_恐龙弟旺仔的博客-CSDN博客
1.Zookeeper客户端由CONNECTING转CONNECTED从笔者之前的博客中可以看出,客户端在创建Zookeeper对象时,状态为CONNECTING,后续通过SendThread.onConnected()方法调用后
class SendThread extends ZooKeeperThread {
void onConnected(int _negotiatedSessionTimeout, long _sessionId,
byte[] _sessionPasswd, boolean isRO) throws IOException {
negotiatedSessionTimeout = _negotiatedSessionTimeout;
...
if (!readOnly && isRO) {
LOG.error("Read/write client got connected to read-only server");
}
readTimeout = negotiatedSessionTimeout * 2 / 3;
connectTimeout = negotiatedSessionTimeout / hostProvider.size();
hostProvider.onConnected();
sessionId = _sessionId;
sessionPasswd = _sessionPasswd;
// 在这里将状态设置为CONNECTED
state = (isRO) ?
States.CONNECTEDREADONLY : States.CONNECTED;
...
}
}
在这里完成了连接,认证了sessionId,协商了超时时间。
2. Socket异常之后的操作客户端发送ping信息以及请求包信息都是通过SendThread.run方法。
当服务端异常时,通过Socket发送请求包就会抛出Socket相关Exception,我们来看下SendThread对此类Exception的处理
class SendThread extends ZooKeeperThread {
@Override
public void run() {
...
// 1.state.isAlive() 的判断条件是 this != CLOSED && this != AUTH_FAILED;
// 当客户端状态非CLOSED和AUTH_FAILED时,属于正常状态
while (state.isAlive()) {
try {
// 2.clientCnxnSocket.isConnected() 的判断条件是 sockKey != null;
// 这个sockKey就是SocketChannel注册Selector 连接事件所返回的SelectorKey
// 如果SelectorKey为null,说明这个sockKey被清理掉了,那么就会触发重连Zookeeper server机制
// 那么这个sockKey是什么时候被清理的呢?
if (!clientCnxnSocket.isConnected()) {
if(!isFirstConnect){
try {
Thread.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
LOG.warn("Unexpected exception", e);
}
}
if (closing || !state.isAlive()) {
break;
}
if (rwServerAddress != null) {
serverAddress = rwServerAddress;
rwServerAddress = null;
} else {
serverAddress = hostProvider.next(1000);
}
// 2.1 在这里重连
startConnect(serverAddress);
clientCnxnSocket.updateLastSendAndHeard();
}
if (state.isConnected()) {
...
} else {
to = connectTimeout - clientCnxnSocket.getIdleRecv();
}
if (to
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?