nginx 的 lingering_close 是一种有界、非阻塞、主动丢弃式等待机制,用于在关闭连接前安全收取客户端可能追加的末尾字节,避免因立即断连触发 RST;它不解决数据丢失,不替代 HTTP 完整性校验,仅适用于无明确长度标识的 HTTP/1.0 等脆弱场景。

nginx 的 lingering_close 不是“智能控制”,而是一种**有界、非阻塞、主动丢弃式等待机制**,目标明确:在连接即将关闭时,安全收完客户端可能追加的最后几字节(比如调试工具多发的换行或 header),避免因立即断连触发 RST,导致客户端收到不完整响应或连接重置异常。
理解 lingering_close 的真实作用边界
它不解决数据丢失问题,也不替代 HTTP 协议层的完整性保障(如 Content-Length 或 Transfer-Encoding: chunked)。它的价值只在一种脆弱场景下生效:HTTP/1.0 或无明确长度标识的响应,客户端依赖 TCP 关闭信号判断响应结束。此时若服务器过早发 FIN 或 RST,客户端就可能截断 body。
- 它不是 keepalive:不维持连接复用,而是“准备关了,先听两秒”
- 它不读取或处理客户端数据:收到即丢弃,不参与业务逻辑
- 它不依赖系统
SO_LINGER:自己用非阻塞read()轮询,避免阻塞 worker 进程
配置 lingering_close 的核心参数
该机制由三个指令协同控制,需配合使用:
-
lingering_close on | off | always:开关总控。on(默认)仅对非 keepalive 连接启用;always强制所有连接进入 lingering 状态(慎用,增加延迟);off完全禁用(等价于立即调用close()) -
lingering_time 30;:最大等待时长(秒),默认 30。建议设为 5–10 秒——足够捕获常见乱序/补发,又不拖慢连接释放 -
lingering_timeout 5;:单次read()超时(毫秒),默认 5。决定轮询灵敏度,一般保持默认即可
与 SO_LINGER 的关键区别和规避要点
不要混淆 nginx 的 lingering_close 和底层 socket 的 SO_LINGER。后者由应用代码直接设置,会引发阻塞或强制 RST,而 nginx 完全绕过了它:
- 若你在自研服务中手动设置了
l_onoff=1, l_linger=0,close()会立刻发 RST——这正是lingering_close要避免的行为 - nginx 不使用
SO_LINGER,所以无需在代码里配置它;它的 lingering 是纯用户态逻辑,不影响内核 socket 状态 - 真正要防 RST 异常,重点是确保响应头含
Content-Length或启用 chunked 编码,让客户端不依赖连接关闭事件
验证是否生效与典型误判
可通过 tcpdump 抓包观察 FIN 交互节奏:
- 启用后:服务器发 FIN 后,会有短暂空闲期(
lingering_time内),期间若收到客户端数据,仅回复 ACK,不发 RST - 禁用后:服务器发 FIN 后立即进入 FIN_WAIT_2,若此时客户端再发数据,内核直接回 RST
- 注意:浏览器开发者工具显示 “ERR_CONNECTION_RESET” 多数源于客户端侧(如代理中断、本地防火墙),而非 nginx lingering 配置问题

















