LISTEN 状态与两个队列
LISTEN 是服务端套接字的状态:内核已经绑定了地址和端口,等待客户端发起连接。连接不是一步进入应用的——内核先用半连接队列暂存收到 SYN 但握手未完成的连接,握手完成后再放入全连接队列,等应用调用 accept 取走。两个队列的长度上限决定了服务在突发流量下能不能扛住。
基本信息
| 半连接队列 | SYN_RCVD 状态的连接,容量受 tcp_max_syn_backlog 影响 |
|---|---|
| 全连接队列 | 已完成握手但应用未 accept,长度取 min(应用 backlog, net.core.somaxconn) |
| 查看工具 | Linux 用 ss -lnt / ss -lntp,老系统用 netstat -lntp |
| 队列水位 | ss -lnt 中 Recv-Q 是当前排队数,Send-Q 是该套接字队列上限 |
| 溢出表现 | 客户端偶发连接超时或重置,高峰期尤其明显 |
典型使用场景
- 部署新服务后确认监听地址与端口是否正确,避免只监听了 127.0.0.1
- 排查「连接被拒绝」:先确认目标端口处于 LISTEN,再查防火墙与安全组
- 高峰期偶发连接超时时,观察 Recv-Q 是否长期贴着 Send-Q
- 上线前评估 backlog 与 somaxconn 是否匹配预计并发连接速率
- 确认哪个进程占用了端口,处理端口冲突或残留进程
- 核对容器内监听与宿主机端口映射是否一致
最小示例
最小示例
ss -lntp # 列出所有 LISTEN 套接字及进程
ss -lnt '( sport = :8080 )' # 只看 8080 端口
ss -lnt | awk 'NR>1 {print $2, $4}' # 查看各套接字 Recv-Q / Send-Q
netstat -s | grep -i -E 'listen|overflow' # 累计的队列溢出计数
cat /proc/sys/net/core/somaxconn # 全连接队列的硬上限
cat /proc/sys/net/ipv4/tcp_max_syn_backlog # 半连接队列参考上限ss -lnt 逐列读法
| 列 | 含义 | 阈值判断 |
|---|---|---|
| State | 套接字状态 | 应为 LISTEN(UDP 显示 UNCONN) |
| Recv-Q | LISTEN 下表示当前已排队的连接数 | 持续接近 Send-Q 说明 accept 跟不上 |
| Send-Q | LISTEN 下表示该队列上限 | 远小于并发峰值时需要调大 |
| Local Address:Port | 监听地址与端口 | 0.0.0.0 对外可连,127.0.0.1 仅本机 |
| Process | 占用该端口的进程 | 与预期进程不符说明端口被抢占 |
调大队列前先看应用是否 accept 太慢:队列加长只是把丢连接变成排队等待,客户端感知仍是超时。单进程同步 accept 的服务,加量往往比调参更有效。