首页/网络/抓包与流量分析速查/TCP 握手慢:accept 队列视角
TCP 流分析82 条

TCP 握手慢:accept 队列视角

服务端收到 SYN 会先入半连接队列,完成握手后进入 accept 队列等待应用 accept():应用 accept 慢会导致已完成连接排队,表现为建连成功但业务无响应。

握手慢的队列视角

服务端收到 SYN 后先在半连接队列等待握手完成,握手完成后连接进入全连接队列,等着应用调用 accept 取走。如果应用取走的速度跟不上,队列就会积压:表现是建连看起来正常,但业务迟迟没有响应。抓包能确认握手已完成,下一步要转到服务端看队列与应用状态。

基本信息

适用平台Linux(ss、nstat 等工具);其他系统有对应实现
观察命令ss -lnt 查看监听套接字队列,ss -s 看整体统计
队列类型半连接队列(完成握手前)与全连接队列(等待被取走)
典型症状三次握手齐全但首字节响应很慢或超时

典型使用场景

  • 建连与接单分离:确认握手正常后把问题交回应用侧
  • 队列积压排查:查看监听套接字的队列深度与溢出计数
  • 容量规划:根据业务并发评估队列与工作进程数量
  • 排查静默丢弃:全连接队列溢出时的行为取决于内核设置
  • 串联证据:结合应用线程池、CPU 与日志一起判断

查看方式

查看方式
ss -lnt                          # 查看监听队列,关注两列队列深度
ss -s | grep -i listen            # 整体监听统计
nstat -az | grep -i -E 'listen|overflow'   # 队列溢出计数
# 队列积压时同步检查应用:线程池、工作进程与 CPU 使用率

队列相关指标

指标含义异常表现
半连接队列深度尚未完成握手的连接数遭遇 SYN 洪泛时明显上升
全连接队列深度已握手等待被取走的连接数应用 accept 慢时持续增长
溢出计数因队列满被丢弃的连接持续非零说明容量不足
应用侧并发数实际正在处理的请求量与队列深度互相印证
抓包看到三次握手完整,并不能证明服务端已经开始处理业务。握手由内核完成,应用有没有空来 accept 是下一层的事,判断时必须结合服务端指标。
全连接队列溢出时的处理方式取决于内核参数:有的实现直接丢弃,有的回 RST。抓到 RST 时不要只往防火墙方向想,先确认队列是否溢出。
队列深度与工作进程数应一并规划。单纯调大队列只能延缓积压,解决不了处理能力不足的问题,积压最终还是会表现为业务超时。

易错点

  • 队列积压与 CPU 饱和常同时出现,先看应用进程负载再调队列
  • 全连接队列溢出的行为(丢弃或回 RST)取决于内核参数,抓到 RST 别只怪防火墙
  • 只调大队列不解决处理能力问题,积压最终仍会表现为业务超时
  • 抓包点看不到队列状态,必须到服务端取数,别用抓包结论替代

数据来源与参考

  • Linux ss 手册
  • RFC 9293(连接建立)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌