nginx的lingering_close机制核心目标是安全收完客户端可能追加的剩余数据,避免粗暴断连导致响应截断或RST异常;它非为复用连接,而是在准备关闭时主动等待并丢弃客户端冗余数据,确保响应完整发出后再真正关闭。

nginx 的 lingering_close 机制,核心目标不是延长连接寿命,而是**在连接即将关闭前,安全收完客户端可能还在发的剩余数据**,从而避免因粗暴断连导致响应被截断、客户端收到不完整内容或 RST 异常。它与 keepalive 完全不同——keepalive 是为复用连接而“留着不关”,lingering_close 是“准备关了,但先等一等”。
为什么需要 lingering_close?
HTTP 协议本身不强制要求客户端在发送完请求后立刻关闭连接。尤其在以下场景中,客户端可能在服务器已开始写响应后,仍追加少量数据(如表单提交末尾的换行、调试工具补发的 header 字段、某些代理行为):
- 客户端使用 HTTP/1.0 或未声明
Connection: close,但实际未严格遵循协议 - 移动端网络不稳定,TCP 报文重传或乱序导致部分请求数据晚到
- 前端 SDK 或测试脚本在发出请求后又调用
socket.write()补充数据
若此时 nginx 立即调用 close(),内核可能直接发送 RST 终止连接,客户端尚未读完的响应 body 就会丢失,浏览器显示“不完整的响应”或触发重试逻辑。
lingering_close 如何工作?
nginx 不依赖系统级 SO_LINGER(因其会阻塞),而是自行实现非阻塞延迟关闭流程:
- 当请求处理完成、判定该连接不再用于 keepalive 后,进入 lingering 状态
- 调用
shutdown(SHUT_WR),向客户端发送 FIN,表明“我不会再发数据了” - 继续调用
read()轮询接收缓冲区,最多等待lingering_time秒(默认 30s) - 若期间收到数据,立即丢弃(不参与响应);若超时或读到 EOF(对方也 FIN),则真正调用
close()
这个过程确保:服务器已发完全部响应,且确认客户端没有“偷偷多发”的数据干扰后续连接复用或日志统计。
响应完整性靠什么保障?
lingering_close 本身不保证响应完整性,它只防止“因关闭太急而丢响应”。真正的完整性由 HTTP 层规则决定:
- 有
Content-Length:客户端按指定字节数接收,收满即停,与连接是否关闭无关 - 启用
Transfer-Encoding: chunked:客户端解析 chunk 格式,见到0\r\n\r\n尾块即认定结束 - 两者皆无(HTTP/1.0 fallback):客户端只能依赖 TCP 连接关闭事件作为响应终点——这正是 lingering_close 要谨慎处理的环节:不能早关(丢数据),也不能死等(资源耗尽)
所以,lingering_close 是在最脆弱的“无长度标识”场景下,为响应完整性提供的最后一道缓冲。
配置与调优建议
通过以下指令控制行为:
-
lingering_close on | off | always:默认on(仅对非 keepalive 连接启用);always强制所有连接都走此流程 -
lingering_time 30:最大等待秒数,建议保持默认;高并发场景可降至 10–20s -
lingering_timeout 5:每次read()调用的超时,避免单次卡住,通常无需调整 - 搭配
reset_timedout_connection on可进一步清理僵死连接
注意:若后端是 FastCGI/uWSGI,还需检查其自身是否有类似 linger 行为,避免双重延迟。










