什么是lingering_close?
lingering_close是延迟关闭,当Nginx要关闭连接时,并非立即关闭连接,而是先关闭tcp连接的写,再等待一段时间后在关闭连接的读。
为什么要有lingering_close?
Nginx在接收客户端请求的时候,如果客户端或服务端出错,Nginx要立即响应错误信息给客户端,在它响应错误信息后,大部分情况下需要关闭当前连接。
Nginx执行完write)系统调用把错误信息发送给客户端,write)系统调用返回成功不代表数据已经发送到客户端,有可能还在tcp连接的write buffer里,如果直接执行close)系统调用关闭tcp连接,内核会先检查tcp的read buffer里有没有客户端发过来的数据留在内核态没有被用户态进程读取。如果有则发送客户端RST报文Reset the connection用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求)来关闭tcp连接丢弃write buffer里的数据,,如果没有则等待write_buffer的数据发送完毕后再4次挥手报文断开连接。
由上可知,如果write buffer里的数据在write) 系统调用后到close)系统调用前没有发送完毕,且read buffer里有数据没有读,就会导致客户端收到RST报文且不会拿到服务端发送的错误信息。这个场景是因为服务端给客户端发送了RST报文导致自己发送的数据在客户端被忽略了。
解决方案如下,我们关掉tcp连接的写,读正常进行,此时客户端再发数据来,就不会受到RST。Nginx还会设置一个超时时间lingering_timeout,超过这个时间内还没有收到数据则关掉连接,而正常的客户端在读取到数据后也会关掉连接。
lingering_time
Nginx中设置的连接的总的读取时间,就是通过lingering_time来设置,这个时间也是Nginx关闭写之后保留socket的时间,客户端需要在这个时间内发送完所有数据,否则Nginx在这个时间后会直接关掉连接。
lingering_close的优缺点
可以保持更好的客户端兼容性,但是会消耗更多的额外资源(比如连接会一直占着)。
以上总结参考链接https://mp.weixin.qq.com/s/bXtI45d7M-XjkJH3ARZiMQ