当 stub_status 中 handles 与 accepts 的差值持续显著增大(如超数千),表明存在大量已接受但未正常处理的僵尸连接;accepts 是成功 accept() 次数,handles 是完成初始化并纳入管理的连接数,理想情况下二者应基本相等。

当 stub_status 中 handles 与 accepts 的差值持续显著增大(例如超过数千),通常表明存在大量已接受但未被正常处理的连接,即僵尸连接堆积。
理解 handles 与 accepts 的含义
accepts:Nginx 自启动以来成功调用 accept() 系统调用的次数,代表内核已完成三次握手、并移交到 Nginx 的连接数。
handles:Nginx 实际完成初始化(如分配 connection 结构体、设置读写事件)并纳入自身连接池管理的连接数。
理想情况下二者应基本相等或差值极小。若 handles < accepts,说明有连接被内核“交过来”了,但 Nginx 没能完成后续接管 —— 这往往就是僵尸连接的起点。
差值异常增大的典型原因
-
worker 进程忙于 CPU 密集型任务:如未优化的 Lua 脚本、正则回溯、大量 sync SSL handshake,导致无法及时调用
ngx_event_accept() - 连接队列积压在内核 backlog 中:`listen` 指令未配 `backlog=` 或系统 `net.core.somaxconn` 过小,造成 accept() 调用延迟,部分连接超时断开前已被计入 accepts
- worker_connections 设置过低 + 高并发短连接:连接快速建立又关闭,但旧连接未被及时回收(如 keepalive 未生效、客户端不发 FIN),connection pool 耗尽后新 accept 失败,但 accepts 仍计数
- 第三方模块阻塞事件循环:如某些未异步化的 upstream 模块、同步 DNS 查询,在 accept 阶段卡住 worker
快速定位与验证方法
执行 curl http://127.0.0.1/nginx_status,观察输出中:
server accepts handled requests
18923456 18919872 22456789
此处 accepts - handles = 3584,若该值在 1 分钟内增长 >500,且 Active connections 并未同步上升,则高度可疑。
进一步确认:
- 检查
netstat -s | grep -i "listen overflows":若有非零输出,说明内核 listen queue 溢出,accepts 虚高 - 用
ss -n state syn-recv | wc -l查看半连接(SYN_RECV),排除 SYN Flood 干扰 - 对比
Active connections与worker_connections × worker_processes:若前者远小于后者但 handles/accepts 差值大,说明连接卡在“已 accept 未 handle”状态
缓解与修复建议
- 调高
listen ... backlog=4096,并同步增大系统参数:sysctl -w net.core.somaxconn=65535 - 确保
worker_connections留有余量(建议 ≤ 单 worker 可用文件描述符上限的 70%) - 启用并合理配置
keepalive_timeout和keepalive_requests,减少短连接冲击 - 审查 Lua/NJS 脚本,避免阻塞操作;对上游调用强制使用异步方式(如 lua-resty-http 的 cosocket)
- 开启
debug_connection对可疑 IP 抓取 error log,搜索"accept() failed"或"no free connections"类错误

















