RST产生的原因
原因概述
正常情况tcp四层握手关闭连接,rst基本都是异常情况,整理如下:
GFW
对方端口未打开,发生在连接建立
如果端口打开,只是sync_backlog满了的话,sync简单被丢弃,表现为超时,而不会rst。Close Socket 时recv buffer 不为空
例如,客户端发了两个请求,服务器只从buffer 读取第一个请求处理完就关闭连接,tcp层认为数据没有正确提交到应用,使用rst关闭连接。移动链路
移动网络下,国内是有5分钟后就回收信令,也就是IM产品,如果心跳>5分钟后服务器再给客户端发消息,就会收到rst。也要查移动网络下IM 保持<5min 心跳。负载等设备
负载设备需要维护连接转发策略,长时间无流量,连接也会被清除,而且很多都不告诉两层机器,新的包过来时才通告rst。
Apple Push 服务也有这个问题,而且是不可预期的偶发性连接被rst;rst 前第一个消息write 是成功的,而第二条写才会告诉你连接被重置,
曾经被它折腾没辙,因此打开每2秒一次tcp keepalive,固定5分钟tcp连接回收,而且发现连接出错时,重发之前10s内消息。SO_LINGER
同第三条,默认SO_LINGER选项关闭, 直接丢弃未发送完毕的send buffer,并发送rst,业务上表示为对端数据未收到;
建议打开,但在linger time 内仍然未将buffer发送完,那依然发送rst。
好像曾经测试过haproxy 某种配置下,会使用rst关闭连接,少了网络交互而且没有 TIME_WAIT 问题超过超时重传次数、网络暂时不可达
TIME_WAIT 状态
tw_recycle = 1 时,sync timestamps 比上次小时,会被rst设置 connect_timeout
应用设置了连接超时,sync 未完成时超时了,会发送rst终止连接。非正常包
连接已经关闭,seq 不正确等keepalive 超时
公网服务tcp keepalive 最好别打开;移动网络下会增加网络负担,切容易掉线;非移动网络核心ISP设备也不一定都支持keepalive,曾经也发现过广州那边有个核心节点就不支持。
实例分析
- 业务表现:业务监控偶现超时,客户端连接服务端偶现被掐掉连接(服务端返回fin)
- 网络链路:lb1->nginx->lb2->服务
- 问题分析
- 查询nginx日志及监控正常
- 查询服务日志及监控正常
- 业务量变化:前一天出现一波业务高峰,现状观察服务水位线处于安全水位
- 根据现有状态未发现明显问题
- 现场复现
- 模拟请求
- 发现客户端已经发到平台但没有到服务器,出现部分请求丢失
- 进行链路抓包
- 发现lb2分别给nginx及服务发了rst
- 经过排查定位到lb2超时时间设置过长造成连接未及时清理
- 缩短超时时间即可