问题现象
公司同事使用的时候,反馈系统不稳定,访问的时候,有时候会出现白屏(连接超时),或者系统页面点击没有响应,过一会之后刷新系统又可以正常展示了。之前未收到过类似反馈,一直都是正常的。
浏览器控制台信息如下
可疑点
所有请求,request header显示的是临时报文头
chrome.devtools上面的介绍
按网上资料,可能和chrome浏览器插件有关系
前面几个请求耗时很久,均卡在Stalled这个状态
问题排查
查看异常附近时段的监控。服务器cpu、内存、带宽、网络连接数无明显变化,未发现异常。
查看服务端应用、入口nginx组件的日志,未看到异常信息,没有看到请求处理超时。
客户端抓包,发现SYN请求建立连接,服务端没有回SYN+ACK。
服务器抓包,未针对SYN包进行响应。
基于这个信息查询,定位系统开启了TCP连接复用参数(tcp_tw_recyle)。和运维沟通,近期针对tcp连接参数进行过调整。恢复了调整参数,然后反馈服务正常。
为什么会丢弃SYN包
服务器任务该数据包是无效的包,故丢弃了。
启用了tcp_tw_recyle之后,开启了per-host的PAWS检查。但数据包里面的时间戳比上一次小,忽略该数据包。
相关知识串联
TCP基础知识点
- TCP/IP的职能定位
- IP,提供的是端到端的传输。从源IP传输到目标IP,选择合适的传输路线,但不保证可靠性。尽力而为。
- TCP,在IP的基础上,提供点到点的服务。从源IP的源端口传输到目标IP的目标端口,保证同一个连接下传输的有序、可靠。
- 如何识别同一个TCP连接
- 通过四元组识别,四元组:源IP、源端口、目标IP、目标端口(还有一个隐性条件:协议类型)。这四个信息一样的即认为同一个TCP连接。
- TCP有序性保障
- 在每个传输的报文段里面添加了sequence信息,接收方接收到数据后进行应答,告知发送方已收到相应的sequence数据。由于网络的不可靠性,可能会出现丢包,或者延时的情况。如接收方已接收到sequence 10000及之前所有的数据包并进行了处理,此时如果收到该sequence之前的包,会丢弃掉不进行处理。(此处为理解问题进行了简化,实际上也会回ack应答)
- sequence标识的是传输内容字节的顺序,而非报文的序号。sequence有长度限制(32bit),最大为4G(2^32),当超过上限后会循环开始。
PAWS+时间戳选项的起因
- 高速带宽+接收方接收能力提升导致sequence不够用,为了解决sequence不够用的场景,增加时间戳用于辅助识别数据包的有效性
- 见下面截图介绍(来源于TCP/IP详解*卷一)
- 见下面截图介绍(来源于TCP/IP详解*卷一)
TCP挥手过程
见下图。主动发起断开方最后需要等待2MSL时间
TCP连接复用+快速回收
tcp_tw_recycle:快速回收TIME_WAIT状态的连接;不推荐在NAT模式下使用;
tcp_tw_reuse:快速复用TIME_WAIT状态的连接;
NAT联网介绍
图片来源于《计算机网络*自顶向下方法》
per-host PAWS机制
当开启了tcp_tw_recycle和tcp_timestamps之后,会开启per-host的PAWS机制,tcp识别由连接的识别由四元组(源IP、源端口、目标ip、目标端口)变为三元组(源IP、目标ip、目标端口)。
问题产生过程
server端是linux系统,默认开始了tcp_timestamps机制。现在又开启了tcp_tw_recycle。
客户端电脑,一般都是NAT联网。不同电脑的时间戳是不一样的。
当A电脑和server端交互完成后,B电脑马上和server端交互,且时间戳比A小。server端会认为是一个无效的包,丢弃它。
验证的部分场景截图
server端主动断开(相同的四元组),syn包被忽略。第二次请时间戳<第一次时间戳
client主动断开(不同的四元组),syn包没有应答。一台client关闭了timestamp选项
相同的四元组,server端主动断开,有应答。第二次请时间戳>第一次时间戳
不同的四元组,server端主动断开,有应答。第二次请时间戳>第一次时间戳(第一台的client关闭了timestamp)
参考资料
syn丢弃场景介绍
tcp_tw_recycle引发的问题
TCP时间戳介绍
附*系列文章索引
整理起因
报文分析
报文格式解读
握手+挥手过程状态变化分析
滑动窗口介绍
可靠数据传输原理
拥塞控制
网络异常案例(1、2、3、4、5)