心跳(HeartBeat)
在计算机领域中,有很多概念和机制的命名,都参考了现实生活中已有的事物或者概念,两者之间一般都具有共同或者相似的行为。
例如:
- 容器
- 树
- 迭代器/游标
- 父类、子类
- 神经网络
- 心跳
为何需要心跳机制
- C/S架构的软件,采用长连接时,通常并不会一直都会有数据传输的。连接处于空闲状态的时间占有相当比例。如果客户端发生崩溃、断网等异常情况时,除非在此连接上继续发送数据产生错误返回,否则服务器无法得知客户端真的出现异常情况了。想要及时得知这一情况并做相应处理的话,就需要心跳机制。
- 另一方面,app经常需要和服务器及时同步一些数据,也可以通过心跳包发送过去。
TCP内置的KeepAlive保活机制
- 7,200,000 ms:TCP默认的心跳间隔时间是2个小时!,这在绝大多数APP中是无法忍受的。
- 这就要提出另外一个问题:心跳间隔时间的不合理设置,可能会因为短暂的网络波动而断开健康的TCP连接。
实践中的疑虑
参与开发中的一个项目,心跳的间隔时间是8秒。检测到玩家断线时,客户端会有断线重连的提示。
现在遇到这样的bug:
流程如下:
玩家点击某个按钮 => 发送消息至服务器 => 服务器处理后,返回消息给客户端 => 客户端做出对应的UI表现
玩家反馈:
点击按钮没有任何反应,没有断线重连提示,服务器日志没有查到这位玩家发送的消息日志。
我猜想:
玩家在点击按钮的时候,正好网络波动网络消息没有发出去,他没有看见断线重连的提示,是因为:短暂之后(8秒之内)网络又好了。也就是说恰好网络波动只是出现在两次心跳之间,而没有被客户端检测到。所以玩家觉得网络没有任何问题(依据是客户端的断线重连提示),服务器日志却又查不到发送网络消息的日志。