zookeeper 的心跳
假定:主机 A, B 通过 tcp 连接发送数据,如果拔掉 A 主机的网线,B 是无法感知到的。但是如果 A 定时给 B 发送心跳,则能根据心跳的回复来判断连接的状态。
以 zookeeper 为例:zk client 会记录上一次发送数据的时间(lastSend)和上一次接收数据的时间(lastHeard),zk client 给 server 发送心跳(ping),这些心跳和其他命令一起发送给 zk server,如果 zk client 发现好长的时间没有接收到数据,认为超时,则断开与 server 的连接,并重连服务器。
// zookeeper 3.3.3
// void org.apache.zookeeper.ClientCnxn.SendThread.run()
public void run() {
long now = System.currentTimeMillis();
long lastHeard = now;
long lastSend = now; // 这里的 zooKeeper 是客户端
while (zooKeeper.state.isAlive()) {
try {
if (sockKey == null) {
// don't re-establish connection if we are closing
if (closing) {
break;
}
// 连接 zk server
startConnect();
lastSend = now;
lastHeard = now;
}
int idleRecv = (int) (now - lastHeard);
int idleSend = (int) (now - lastSend);
int to = readTimeout - idleRecv;
if (zooKeeper.state != States.CONNECTED) {
to = connectTimeout - idleRecv;
}
// 接收数据超时,抛异常,异常会在后面的 catch 块中处理
if (to <= 0) {
throw new SessionTimeoutException(
"Client session timed out, have not heard from server in "
+ idleRecv + "ms"
+ " for sessionid 0x"
+ Long.toHexString(sessionId));
}
if (zooKeeper.state == States.CONNECTED) {
int timeToNextPing = readTimeout/2 - idleSend;
// 发送 ping 命令(心跳),更新 lastSend
if (timeToNextPing <= 0) {
sendPing();
lastSend = now;
enableWrite();
} else {
if (timeToNextPing < to) {
to = timeToNextPing;
}
}
} selector.select(to);
Set<SelectionKey> selected;
synchronized (this) {
selected = selector.selectedKeys();
}
// Everything below and until we get back to the select is
// non blocking, so time is effectively a constant. That is
// Why we just have to do this once, here
now = System.currentTimeMillis();
for (SelectionKey k : selected) {
SocketChannel sc = ((SocketChannel) k.channel());
if ((k.readyOps() & SelectionKey.OP_CONNECT) != 0) {
if (sc.finishConnect()) {
lastHeard = now;
lastSend = now;
primeConnection(k);
}
} else if ((k.readyOps() & (SelectionKey.OP_READ | SelectionKey.OP_WRITE)) != 0) {
if (outgoingQueue.size() > 0) {
// We have something to send so it's the same
// as if we do the send now.
lastSend = now;
}
if (doIO()) {
lastHeard = now;
}
}
}
if (zooKeeper.state == States.CONNECTED) {
if (outgoingQueue.size() > 0) {
enableWrite();
} else {
disableWrite();
}
}
selected.clear();
} catch (Exception e) {
if (closing) {
if (LOG.isDebugEnabled()) {
// closing so this is expected
LOG.debug("An exception was thrown while closing send thread for session 0x"
+ Long.toHexString(getSessionId())
+ " : " + e.getMessage());
}
break;
} else {
// this is ugly, you have a better way speak up
if (e instanceof SessionExpiredException) {
LOG.info(e.getMessage() + ", closing socket connection");
} else if (e instanceof SessionTimeoutException) {
LOG.info(e.getMessage() + RETRY_CONN_MSG);
} else if (e instanceof EndOfStreamException) {
LOG.info(e.getMessage() + RETRY_CONN_MSG);
} else {
LOG.warn("Session 0x"
+ Long.toHexString(getSessionId())
+ " for server "
+ ((SocketChannel)sockKey.channel())
.socket().getRemoteSocketAddress()
+ ", unexpected error"
+ RETRY_CONN_MSG,
e);
}
// 断开连接
cleanup();
if (zooKeeper.state.isAlive()) {
eventThread.queueEvent(new WatchedEvent(
Event.EventType.None,
Event.KeeperState.Disconnected,
null));
} now = System.currentTimeMillis();
lastHeard = now;
lastSend = now;
}
}
}
cleanup();
try {
selector.close();
} catch (IOException e) {
LOG.warn("Ignoring exception during selector close", e);
}
if (zooKeeper.state.isAlive()) {
eventThread.queueEvent(new WatchedEvent(
Event.EventType.None,
Event.KeeperState.Disconnected,
null));
}
ZooTrace.logTraceMessage(LOG, ZooTrace.getTextTraceLevel(),
"SendThread exitedloop.");
}
zk server 对 session 也会有一个跟踪,它也会关掉超时的 session,具体逻辑在
void org.apache.zookeeper.server.SessionTrackerImpl.run()
zk server 每收到一个请求,就会触发 touchSession

zookeeper 的心跳的更多相关文章
- zookeeper(单机/集群)安装与配置
一.安装与单机配置 1.下载: wget http://archive.apache.org/dist/zookeeper/stable/zookeeper-3.4.6.tar.gz 如果网站下载不了 ...
- zookeeper dubbo 问题解决录
问题1: 运行起来不报错,不过在Console没有zookeeper的心跳信息,也就是说没有配置上zookeeper,而出错的原因是下面蓝色这段解析不了 spring-dubbo-provider.x ...
- Zookeeper集群的安装和使用
Apache Zookeeper 由 Apache Hadoop 的 Zookeeper 子项目发展而来,现已经成为 Apache 的顶级项目,它是一个开放源码的分布式应用程序协调服务,是Google ...
- dubbo与zookeeper的关系
Dubbo建议使用Zookeeper作为服务的注册中心. 1. Zookeeper的作用: zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是 ...
- spring Boot环境下dubbo+zookeeper的一个基础讲解与示例
一,学习背景 1. 前言 对于我们不管工作还是生活中,需要或者想去学习一些东西的时候,大致都考虑几点: a) 我们为什么需要学习这个东西? b) 这个东西是什么? c) ...
- linux下配置zookeeper注册中心及运行dubbo服务
dubbo和zookeeper的关系 简单来说打个比方:dubbo就是动物园的动物,zookeeper是动物园.如果游客想看动物的话那么就去动物园看.比如你要看老虎,那么动物园有你才能看到.换句话说我 ...
- Zookeeper(一)CentOS7.5搭建Zookeeper3.4.12集群与命令行操作
一. 分布式安装部署 1.0 下载地址 官网首页: https://zookeeper.apache.org/ 下载地址: http://mirror.bit.edu.cn/apache/zookee ...
- 为什么zookeeper会导致磁盘IO高【转】
由于早期的storm版本心跳信息严重依赖zookeeper,心跳风暴会导致zookeeper的事务日志频繁的写磁盘,带来的问题首当其冲的是磁盘IO会爆掉. 优化思路 将zookeeper事务的日志放入 ...
- zookeeper和dubbo的关系
Dubbo建议使用Zookeeper作为服务的注册中心. 1. Zookeeper的作用: zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知 ...
随机推荐
- AmazeUI学习
http://amazeui.org/ 相比于其他国外的框架而言,Amaze UI更关注中文排版,被前端工程师称为最懂中文的前端框架. Amaze UI受欢迎的一个重要的原因是:文档非常完善,适合各阶 ...
- webservice跨域问题
在webconfig里面加上 <httpProtocol> <customHeaders> <add name="Access-Co ...
- 【Cucumber】【命令行】
知识点 参考:https://www.cnblogs.com/worklog/p/5253297.html cucumber的命令行选项 首先查看命令行选项.和其它命令行工具一样,cucumber提供 ...
- _attribute_character
职业属性控制表 comment 备注 classI ...
- Codeforces 781B. Innokenty and a Football League
题目链接:http://codeforces.com/contest/781/problem/B 去tmd 2-SAT 直接贪心就可以过去了,优先选择第二种情况. 然而....可以被叉掉(数据水了) ...
- js,jq获取父,兄弟,子节点整理
js获取节点 父: parentNode 获取已知节点的父节点. 子: childNodes; 得到全部子节点 children 得到全部子节点 firstChild 获得第一个子节点 lastChi ...
- 串口.Qt532测试(异步)
环境:Win7x64.Qt5.3.2 MSVC OpenGL(x86).vs2010(x86) 项目所在位置:E:\Project_Qt532\SeriesPort_Qt532_Z ZC:这里 同步方 ...
- 虚拟机安装---vm12+ubuntukylin16.04
虚拟机安装及部分问题解决方案: https://blog.csdn.net/qq_35208390/article/details/78271743 安装vmware tools后,需设置共享文件夹才 ...
- centos如何查看linux内核,版本号
[root@localhost ~]# uname -a Linux localhost.localdomain -.el7.x86_64 # SMP Thu Nov :: UTC x86_64 x8 ...
- Redisson实现分布式锁(一)
为什么要使用分布式锁? 单机情况下,多线程同时访问并改变临界资源(可变共享变量),将会使得这个变量不可预知,所以我们引入了同步(lock—synchronized).但在分布式场景下(多机部署),业务 ...