握手慢的队列视角
服务端收到 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 时不要只往防火墙方向想,先确认队列是否溢出。
队列深度与工作进程数应一并规划。单纯调大队列只能延缓积压,解决不了处理能力不足的问题,积压最终还是会表现为业务超时。