07 | 保活机制:心跳包异常导致应用重启?
该思维导图由 AI 生成,仅供参考
TCP 长连接为何总中断?
- 深入了解
- 翻译
- 解释
- 总结
本文通过一个案例详细介绍了TCP长连接的应用经常中断问题的原因和解决方案。文章首先解释了客户端发送心跳包的作用以及对加密服务器的健康检查,探讨了Keep-alive与长连接的关系,以及其在应用层代码和操作系统TCP协议栈的实现方式。通过抓包分析和Keep-alive知识点,读者可以深入了解TCP保活机制的原理和应用,以及如何解决长连接失效等问题。文章还介绍了TCP Keep-alive的配置方法和相关全局配置项,以及对Keep-alive报文特征的讨论。此外,文章还详细探究了HTTP Keep-alive的作用和区别,以及在流量调度场景下的实际应用。总的来说,本文通过案例和技术细节,帮助读者快速了解TCP保活机制的相关知识,为解决长连接中断问题提供了有益的参考。
《网络排查案例课》,新⼈⾸单¥59
全部留言(24)
- 最新
- 精选
- 江山如画问题1: 方法1: frame contains abc 方法2: ip contains abc 方法3: tcp contains abc 方法4: http contains abc 方法5: tcp.payload contains 61-62-63 问题2: 工作中目前还没有碰到过和 tcp keep-alive 有关的问题,不过之前看一些建立网络隧道的软件有 keep-alive 这个参数,查询说和 SNAT 有关,一值很迷惑。 今天学习了老师的课又深究了下,virtual tunnel 会建立虚拟网卡,和物理网卡之间需要做流量的桥接,进而需要做 SNAT,SNAT 会维护一个端口映射表,因为链接太多可能会占满本地端口,如果没有设置 keep-alive,在一段时间内都没有传输数据,会把端口转换的记录给删掉,这时候通信双方想再通信就不行了。所以需要每隔一段时间发送心跳包,保证 SNAT 端口映射表中的记录不被删掉,从而保证连接存活。 总结二者的区别: 1. http keep-alive 是七层特性,tcp keep-alive 是四层特性 2. http keep-alive 旨在较短时间内,复用 tcp 链接,快速传输大量数据,减少重复握手挥手带来的时延消耗和网络拥堵,比如用浏览器访问一个带有大量 js,css 或图片的网页; tcp keep-alive 旨在相对较长的一段时间内,检查 tcp 链接是否存活,它的传输频率很低,传输数据量也很小,感觉类似网络隧道软件,语音,聊天软件中可能会用到 tcp keep-alive。 3. http keep-alive 的内部实现不依赖于 tcp keep-alive, 二者实现上没有关系。
作者回复: 你回复的很全面,给你点赞! 如你所述,NAT一般会维护一个连接映射表,而这个表里的表项是有有效期的,也就是过了一定的时间就从表里删除,那么后续两端在这个连接上的报文经过NAT的时候,因为找不到表项,就被判定为无效报文,就会被丢弃。
2022-01-26420 - Geek_535c45老师好,关于TCP的keep-alive,有个疑惑 1、是否开启keep-alive 取决于客户端程序是否调用setsockopt(),而与服务端(被连接方)无关 ? 2、Linux 上的net.ipv4.tcp_keepalive 参数是控制运行在linux上的客户端进程和目标服务之间的长连接保活的参数,与服务器端(假设也为linux)设置的net.ipv4.tcp_keepalive 参数无关 ? 3、HTTP keep-alive 是否依赖TCP keep-alive,如果HTTP的 keep_alive_request_time 比TCP 的keep-alive 时长配置的长,HTTP在开启长连接的情况下客户端请求发起一次之后中间就一直没有再请求,中间这个间隔时长大于了TCP 的keep-alive,是否会中断?
作者回复: 您好,这几个问题质量很高,我说下自己的理解: 1. TCP是全双工的协议,所以两个方向都可以自己选择是否要做keep-alive。如果客户端setsockopt()启用了Keep-alive,那客户端会定时发送保活报文,服务端会回复ack(这个是必做的,跟服务端是否启用保活没有关系)。如果服务端也开启了TCP keep-alive,那就相互发送保活报文。但是,考虑一方的idle timeout会随着另一方发送的保活报文而被刷新,所以是相互有影响的。 比如,客户端10分钟发一次保活,服务端是15分钟发一次保活。那么在第10分钟时,客户端发送了报文,对服务端来说,因为此时接收到了报文,所以idle timeout就被刷新为0了,服务端计划等到第25分钟再发它自己的保活报文。实际上在第20分钟,客户度再次发送保活报文,服务端的idle timeout再次被刷新,所以服务端就不再发送它这端的保活报文了,因为没有机会等满15分钟空闲。 2. 跟1类似,因为是两个方向上自己的选择,所以双方依然可以各自设置保活参数。但实际上我们只会看到间隔更小的那个保活报文。 3. HTTP Keep-alive是告知对方:“我想这次用TCP长连接”,它本身不是定时周期性发送的保活报文。如果HTTP请求耗时超过了TCP保活的时长,那TCP保活报文会按时发送TCP保活报文并得到服务端的ack,这跟HTTP响应什么时候回复出来不矛盾,也无关。 我们还发现,有些web服务器会选择在一个长连接服务了一定数量的HTTP请求之后(比如1000个),选择发送一次Connection:close给客户端,让客户端结束这次连接,这给了客户端一次重新选择服务端的机会(比如LB会新选一个后端服务器给它)。
2022-03-0747 - webmin为什么要心跳检查,因为目前讨论的数据连接场景,都是无源连接,排除NAT的情况,连接就是存在于src和dest两端OS中的状态机,为什么会要用无源连接呢,有源是连接建立带宽就分配好了,不传有效数据这个带宽也被占用着,这不就浪费了,虚拟信号时代的电话就是有源的。 心跳检查是两端都要做的,不做的那一端一样存在状态不对而不自知的情况。
作者回复: 没错,状态机在两端是有可能不一致的,比如一端认为这条连接已经销毁,另外一端可能认为仍有效。心跳机制的作用之一就是解决这种不一致的情况,类似“校对”的作用。
2022-01-266 - 那时刻请问老师,例子中的心跳消息显示push ack是为何呢?
作者回复: 你的疑问是为什么有PSH标志位吗?按照TCP协议(参考RFC793)规定,操作系统收到有PSH标志位的报文后,这些报文不会被驻留在接收缓冲区,而是要立即通知用户空间程序来接收。这样对于用户空间程序及时收发处理心跳报文是有利的。
2022-01-2636 - Cavalier老师您好,我有一台设备网络会时不时就断,但是只要上面一直跑着ping就不会断开。这个有什么思路?
作者回复: 你说的断开,有没有抓到过TCP报文?是收到了RST还是什么呢?RST报文的TTL跟正常连接的TTL有什么不一样吗? 有一个可能性你路径上有防火墙或者NAT,它们会对TCP连接信息进行一定时间的缓存,如果你的长连接中的报文隔了很久才传送,此时可能防火墙/NAT上这个连接的信息已经没有了。 一直跑着ping,虽然跟TCP连接没有直接关系,但不排除这个中间设备会因为持续ping的存在,也把这个源IP相关的TCP连接做了维持。这只是我的一个猜测,供参考~
2022-04-023 - 天问tcp contains "abc"显示包含abc的数据包
作者回复: 正确:)
2022-01-262 - LEON您好,这句话我感觉描述的有问题-----------”客户端收到这个头部后,按照协议规定,它必须关闭这条长连接。在下一次 HTTP 请求的时候,客户端就会遵循“DNS 解析 -> 发起新连接 -> 发送 HTTP 请求”------我理解Connection: Close的调整只会影响HTTP的行为,和DNS 无关,如果客户端LDNS或本地有缓存,也不会重新到GSLB发起新的解析,会基于缓存的老的VS地址链接到老的VS上,从而影响切换。
作者回复: 谢谢您的意见。总的来说,“在下一次 HTTP 请求的时候,客户端就会遵循“DNS 解析 -> 发起新连接 -> 发送 HTTP 请求”这一句没有太大问题。这里说的“DNS解析”可以是从本地解析缓存中获取,也可以到DNS服务器上获取,这都属于解析行为。 不同的操作系统行为不完全一样。windows默认启用dns client service,它会缓存DNS解析记录。linux默认没有dns缓存,但是可以通过安装nscd或者dnsmasq来实现类似的解析缓存。 在ebay的环境里,启用和未启用本地解析缓存的情况都存在。对于没有解析缓存的情况,Connection:close起效快;如果有缓存,起效会慢一点,但最差情况也能在DNS record TTL时间后发起新的解析请求。 当然,这里的讨论没有考虑应用程序做解析缓存的情况(包括jvm也有相关的dns解析缓存的配置),否则可能文章写不完:)
2022-08-03归属地:上海1 - Realm1 tcp.payload include abc 2 我们遇到一个web应用,在浏览器上请求一个需要长时间才得到结果的请求,最后返回超时错误,估计被中间网络设备给reset掉了.
作者回复: 1. 意思对了:) 表达式是tcp.payload contains "abc" 2. 你说的情况我们经常遇到,我估计你说的就是客户端自己的超时设置,也就是如果http响应无法在限定时间内完成(比如1秒内),那么客户端应用程序自己会报timeout错误。这应该不是中间设备做了reset,因为如果是那样,这个中间设备应该会给客户端和服务端都发TCP RST,然后客户端报错会变成ECONNRESET这种(ECONNRESET是linux的网络协议栈报给用户空间程序的报错)
2022-01-2621 - Geek_49b49f如何在vip级别上插入connection close 头部呢?
作者回复: 负载均衡(有时候叫做应用网关、反向代理,其实都是差不多的)一般都带有设置第七层规则的能力。在这里,就是需要插入一个HTTP header,其键是Connection,值是Close。 Connection: Close 具体做法取决于你用的是哪一种产品,查阅相应的产品文档即可。
2023-09-06归属地:广东 - 斯蒂芬.赵看完还是没 明白心跳包为啥异常?能说一下具体跟因是啥么
作者回复: 跟你另外一个问题类似,参考那个的答案:)
2022-12-02归属地:上海