Nginx: recv() failed (104: connection reset by peer) 问题排查
Posted 诗渊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx: recv() failed (104: connection reset by peer) 问题排查相关的知识,希望对你有一定的参考价值。
recv() failed (104: connection reset by peer) 问题排查
最近项目中通过nginx反向代理nodejs(采用nestjs框架)服务,压测过程中概率性出现502 Bad Gateway
,出现概率较低,大概在0.005%左右,查看日志具体报错信息为recv() failed (104: Connection reset by peer) while reading response header from upstream
,通过查找资料,了解到该报错的直接原因就是:
nodejs服务已经断开了连接,但是未通知到Nginx,Nginx还在该连接上收发数据,最终导致了该报错。
考虑到在Nginx中我们配置了打开与nodejs server的长连接,即:
proxy_http_version 1.1;
proxy_set_header Connection "";
我们先从长连接相关的设置入手查找问题,Nginx常用的几个影响长连接的参数设置有:keepalive_timeout
、keepalive_requests
、keepalive
-
1)
keepalive_timeout
: 设置客户端的长连接超时时间,如果超过这个时间客户端没有发起请求,则Nginx服务器会主动关闭长连接,Nginx默认的keepalive_timeout 75s;
。有些浏览器最多只保持 60 秒,所以我们一般设置为60s
。如果设置为0
,则关闭长连接。 -
2)
keepalive_requests
:设置与客户端的建立的一个长连接可以处理的最大请求次数,如果超过这个值,则Nginx会主动关闭该长连接,默认值为100
。一般情况下,
keepalive_requests 100
基本上可以满足需求,但是在 QPS 较高的情况下,不停的有长连接请求数达到最大请求次数而被关闭,这也就意味着Nginx需要不停的创建新的长连接来处理请求,这样会可能出现大量的TIME WAIT
-
3)
keepalive
: 设置到 upstream 服务器的空闲 keepalive 连接的最大数量,当空闲的 keepalive 的连接数量超过这个值时,最近使用最少的连接将被关闭,如果这个值设置得太小的话,某个时间段请求数较多,而且请求处理时间不稳定的情况,可能就会出现不停的关闭和创建长连接数。我们一般设置1024
即可。特殊场景下,可以通过接口的平均响应时间和QPS估算一下。 -
4)开启与 upstream 服务器的长连接
默认nginx访问后端都是用的短连接(HTTP1.0),每次请求来了就新开一个连接,处理完后就关闭该连接,下一次请求再重新开启。HTTP协议中从1.1版本之后开始对支持长连接。因此我们会在location中设置以下参数来开启长连接:
http server location / proxy_http_version 1.1; proxy_set_header Connection "";
1)和 2)是设置客户端和Nginx之间的长连接,3)和 4)是设置 Nginx 和 server 之间的长连接。
以上参数配置都核对过没有问题后,我们开始从node中查找是否有与keepalive相关的配置,通过查找nodejs文档,发现nodejs中默认的server.keepAliveTimeout
时间为 5000ms
,这样如果在 5000s
的超时界限点,Nginx还未收到 Node 端的关闭通知,还继续在该长连接上收发数据,那么就可能出现上述的报错,
因此我们适当加大 node 端的 keepAliveTimeout
值(参考https://shuheikagawa.com/blog/2019/04/25/keep-alive-timeout/):
// Set up the app...
const server = app.listen(8080);
server.keepAliveTimeout = 61 * 1000;
server.headersTimeout = 65 * 1000; // Node.js >= 10.15.2 需要设置该值大于keepAliveTimeout
延长 node 端的 keepAliveTimeout
值的目的就是为了防止 Nginx 的在 node 服务之前断开连接,被调用方的超时时间需要大于调用方。
经过上述修改后,压测时Nginx未出现过502 Bad Gateway
的报错。
以上是关于Nginx: recv() failed (104: connection reset by peer) 问题排查的主要内容,如果未能解决你的问题,请参考以下文章
nginx tomcat7 错误:-“从上游读取响应标头时,recv() 失败(104:对等连接重置)”
[error] 2340#0: *3571 recv() failed (104: Connection reset by peer) while reading response header fr
[error] 2340#0: *3571 recv() failed (104: Connection reset by peer) while reading response header fr
从上游读取响应头时,Nginx uwsgi(104:由对等方重置连接)
反向代理 27833 recv() failed (104: Connection reset by peer) while reading response header from upstream