假定:主机 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 的心跳的更多相关文章

  1. zookeeper(单机/集群)安装与配置

    一.安装与单机配置 1.下载: wget http://archive.apache.org/dist/zookeeper/stable/zookeeper-3.4.6.tar.gz 如果网站下载不了 ...

  2. zookeeper dubbo 问题解决录

    问题1: 运行起来不报错,不过在Console没有zookeeper的心跳信息,也就是说没有配置上zookeeper,而出错的原因是下面蓝色这段解析不了 spring-dubbo-provider.x ...

  3. Zookeeper集群的安装和使用

    Apache Zookeeper 由 Apache Hadoop 的 Zookeeper 子项目发展而来,现已经成为 Apache 的顶级项目,它是一个开放源码的分布式应用程序协调服务,是Google ...

  4. dubbo与zookeeper的关系

    Dubbo建议使用Zookeeper作为服务的注册中心. 1.   Zookeeper的作用: zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是 ...

  5. spring Boot环境下dubbo+zookeeper的一个基础讲解与示例

    一,学习背景 1.   前言 对于我们不管工作还是生活中,需要或者想去学习一些东西的时候,大致都考虑几点: a)      我们为什么需要学习这个东西? b)     这个东西是什么? c)      ...

  6. linux下配置zookeeper注册中心及运行dubbo服务

    dubbo和zookeeper的关系 简单来说打个比方:dubbo就是动物园的动物,zookeeper是动物园.如果游客想看动物的话那么就去动物园看.比如你要看老虎,那么动物园有你才能看到.换句话说我 ...

  7. Zookeeper(一)CentOS7.5搭建Zookeeper3.4.12集群与命令行操作

    一. 分布式安装部署 1.0 下载地址 官网首页: https://zookeeper.apache.org/ 下载地址: http://mirror.bit.edu.cn/apache/zookee ...

  8. 为什么zookeeper会导致磁盘IO高【转】

    由于早期的storm版本心跳信息严重依赖zookeeper,心跳风暴会导致zookeeper的事务日志频繁的写磁盘,带来的问题首当其冲的是磁盘IO会爆掉. 优化思路 将zookeeper事务的日志放入 ...

  9. zookeeper和dubbo的关系

    Dubbo建议使用Zookeeper作为服务的注册中心. 1.   Zookeeper的作用:         zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知 ...

随机推荐

  1. ADO.NET DBHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Da ...

  2. 2018.3 江苏省计算机等级考试 C语言 编程题答案

    题目要求:给定一个数字范围,输出满足这些条件: 1.能被3整除: 2.包含数字5, 将满足的数字放在特定的数组里输出.输出这些数里5出现的个数.数字的个数. 想起来有点伤心,本来很简单的题,考试的时候 ...

  3. 要使用myConfig.properties配置文件作为实体类的映射文件的话,格式要用=,最关键的要和实例类中通过反射获取值的KEY要一样,不样会反射取不到值

    ABC=https://fsdfsdf.iy.comABCId=L2345345ZhP345ABCKey=sfdf4234f234dhE6Ut0aABCName=Gassd010 上面是myConfi ...

  4. 从flask视角学习angular(一)整体对比

    写在前面 前端框架完全不懂. 看着angular中文官网的英雄编辑器教程和核心知识,用偷懒的类比法,从flask django的角度 记录一下自己对angular的理解. 作为工科的武曲,自己的体会是 ...

  5. MySQL学习(十一)

    MySQL的函数 1 数学函数 2 字符串函数 3 日期和时间函数 4 条件判断函数 5 系统信息函数 6 加密解密函数 7 其他函数 2 字符串函数 length计算的是字节长度 char_leng ...

  6. 04-python-闭包

    1.闭包的概念: 官方概念:在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包.闭包可以用来在一个函数与一组"私有"变量之间创 ...

  7. Unity --- 纹理为什么要设置为2的N次方

    1.图片的纹理像素在Unity3D中需要遵循2的N次方,由图形学决定的,只识别2的N次方.   非2的N次方的图片会转化为2的N次方图片(500 x 500 → 512 x 512),是因为转化过程比 ...

  8. Unity--- 纹理设置属性 alphaIsTransparency

    官方的解释: 意思就是没什么实际效果,只是用做显示用. 参考:https://docs.unity3d.com/ScriptReference/Texture2D-alphaIsTransparenc ...

  9. (Gorails视频)使用推广链接(params[:ref]),增加注册用户!

    用一个链接进行用户的注册推广: 我的git:   https://github.com/chentianwei411/embeddable_comments 用途:比如推广,拉朋友注册,给推广码,用这 ...

  10. HDOJ 1023 Train Problem II

    考虑第1个火车出站的时刻,从1到n都有可能,如果它是第i个出栈,那么前面有规模为i-1的子问题,后面有规模为n-i的子问题.累加.