TCP状态概述.md

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超时时间设置过长造成连接未及时清理
    • 缩短超时时间即可