【tcp】心跳检测,保活机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【tcp】心跳检测,保活机制相关的知识,希望对你有一定的参考价值。

参考技术A 为什么要心跳检查?

因为目前讨论的数据连接场景,都是无源连接,排除NAT的情况,连接就是存在于src和dest两端OS中的状态机,为什么会要用无源连接呢,有源是连接建立带宽就分配好了,不传有效数据这个带宽也被占用着,这不就浪费了,虚拟信号时代的电话就是有源的。

心跳检查是两端都要做的,不做的那一端一样存在状态不对而不自知的情况。

状态机在两端是有可能不一致的,比如一端认为这条连接已经销毁,另外一端可能认为仍有效。心跳机制的作用之一就是解决这种不一致的情况,类似“校对”的作用。

在浏览器上请求一个需要长时间才得到结果的请求,最后返回超时错误。

你说的情况我们经常遇到,我估计你说的就是客户端自己的超时设置,也就是如果http响应无法在限定时间内完成(比如1秒内),那么客户端应用程序自己会报timeout错误。

这应该不是中间设备做了reset,因为如果是那样,这个中间设备应该会给客户端和服务端都发TCP RST,然后客户端报错会变成ECONNRESET这种(ECONNRESET是linux的网络协议栈报给用户空间程序的报错)。

心跳消息显示push ack是为何呢?

按照TCP协议(参考RFC793)规定,操作系统收到有PSH标志位的报文后,这些报文不会被驻留在接收缓冲区,而是要立即通知用户空间程序来接收。这样对于用户空间程序及时收发处理心跳报文是有利的。

AWS的nlb keep-alive最大是350s,我们的服务端keep-alive是默认配置,客户端使用了连接池,也进行了探测,但是有个骚操作是随机选取池子里面的一个链接进行探测,然后那些超过350s还没探测的链接,再次使用就出问题了。

你说的“随机选取池子里面的一个链接进行探测”,我判断是健康检查,就是业务健康性(类似k8s的readiness probe),而不是keepalive。

如果是这样的话,这个健康检查确实不是为保活而生的,也很难达到保活的目的。建议这样做设置:client idle timeout < LB idle timeout < server idle timeout,这样可以尽可能的保证不出现连接失效的情况。

这里说的“保活时间”,不是心跳包的间隔,而是空闲保活时间,idle timeout。

保活机制:心跳包异常导致应用重启?

https://time.geekbang.org/column/article/482610

如何解决 Keep-Alive 导致 ECONNRESET 的问题

https://zhuanlan.zhihu.com/p/86953757

解决使用 KeepAlive Agent 遇到的 ECONNRESET

https://zhuanlan.zhihu.com/p/34147188

netty 心跳包和断线重连机制

参考技术A 心跳包主要是用来做TCP长连接保活的。有时 socket 虽然是连接的但中间网络可能有问题,这时你还在不停的往外发送数据,但对方是收不到的,你不知道对方是不是还活着,不知道 socket 通道是不是还是联通的。 心跳包就是你发送一些试探包给对方,对方回应,如果一定时间内比如30秒内没有收到任何数据,说明对方或网络可能有问题了。这时你主动断开 socket 连接,避免浪费资源。

TCP keepAlive 也是在一定时间内(默认2小时)socket 上没有接收到数据时主动断开连接,避免浪费资源,这时远端很可能已经down机了或中间网络有问题。也是通过发送一系列试探包看有没有回应来实现的。

TCP keepAlive 依赖操作系统,默认是关闭的,需要修改操作系统配置打开。
所以在应用层实现心跳包还是必须的。

这个是显而易见的,正常通信时说明两端连接是没有问题的,所以只在空闲的时候发送心跳包。如果每隔固定时间发送就会浪费资源占用正常通信的资源。

假设现在要做一个手机端推送的项目,所有手机通过 TCP 长连接连接到后台服务器。心跳机制是这样的:

看其他博客说不要回复,如果有 10万空闲连接,光回复心跳包就要占用大量资源。服务端读超时后直接关闭连接,客户端再进行重连。

断线重连也很简单就是在 channelInactive 的时候重新 connect 就行了。参考其他博客专门用一个 ChannelInboundHandler 来处理断线重连。

这个 watchDog Handler 应当放在 ChannelPipeline 的最前面

其实客户端和服务端都是相对的,这个看应用场景。如果客户端想要及时处理断网,路由故障等情况就需要接受服务端发来的心跳来检测。像断网,路由故障这种情况,两边都不知道TCP连接的状态,必须靠心跳。长连接服务端一般都要接收心跳包的,如果没有心跳可能会有大量的无效连接,直接耗尽服务器资源,无效的连接要尽早关闭掉。

DEMO:
https://github.com/lesliebeijing/Netty-Demo

基于 Netty 写的一个简单的推送 DEMO,可用在手机端推送
https://github.com/lesliebeijing/EncPush

Netty 客户端用在 Android 中也很稳定,我们的物联网项目Android和后台都是用的 Netty。

以上是关于【tcp】心跳检测,保活机制的主要内容,如果未能解决你的问题,请参考以下文章

TCP连接探测中的Keepalive和心跳包

如何在socket编程的Tcp连接中实现心跳协议

WebSocket 心跳检测和重连机制

iOS 即时通讯(二):心跳保活

TCP keepalive长连接心跳保活

基于TCP的移动端IM即时通讯开发仍然需要心跳保活