Connection reset by peer 是对端主动发送 TCP RST 包导致的强制断连,需通过 Nginx 错误日志上下文、IP 分布、时间规律初步定位来源(后端/客户端/中间设备),再用 tcpdump + tshark 抓包确认 RST 发送方,最后针对性排查 OOM、连接超时、防火墙策略等根因。

看到大量 Connection reset by peer,别急着调 Nginx 配置——它不是 Nginx 出错,而是对端(客户端、后端服务或中间设备)主动发了 TCP RST 包,把连接硬掐断了。关键在“谁发的、为什么发”。先看日志上下文定方向,再抓包确认源头。
第一步:从 error.log 上下文判断 RST 来自哪边
错误本身不说话,但前后文字会指路:
-
含
while reading response header from upstream或upstream prematurely closed connection→ RST 极大概率来自后端(Tomcat/PHP-FPM/Node.js 等),不是客户端也不是 Nginx 自己 -
含
while sending to client或错误分散在大量不同 IP 和 URL → 更可能是客户端侧中断(浏览器关闭、小程序退后台、爬虫断连、移动端切网) - 错误集中爆发,比如每 5 分钟一批,且后端日志完全没异常 → 留意中间设备:云厂商 SLB、WAF、防火墙空闲超时强制回收连接
第二步:快速缩小范围的三类检查
不用全盘翻日志,聚焦三个关键点:
-
查时间规律:用
grep "reset by peer" /var/log/nginx/error.log | head -20 | awk '{print $1,$2,$3}'看是否固定间隔出现;周期性报错大概率是中间设备或后端空闲超时 -
查客户端 IP 分布:用
awk '/reset by peer/ {print $NF}' /var/log/nginx/error.log | sort | uniq -c | sort -nr | head -10看是不是集中在少数 IP(可能是爬虫或攻击)还是高度分散(更倾向客户端行为) -
对照 access.log:提取报错请求的
$request_time和$upstream_response_time;若后者为-或极小,说明请求根本没发到后端;若接近proxy_read_timeout值,后端响应慢或卡死可能性高
第三步:必须抓包,否则永远猜不准
日志只能推测,抓包才能实锤谁发了 RST:
- 在 Nginx 服务器上执行:
tcpdump -i any 'host 后端IP and port 443' -w rst.pcap(HTTPS 后端)或tcpdump -i any 'host 后端IP and port 8080' -w rst.pcap(HTTP) - 过滤 RST 包:
tshark -r rst.pcap 'tcp.flags.reset == 1' - 重点看输出中 RST 包的源 IP:是后端服务器 IP?SLB 的 VIP?还是某个公网客户端 IP?源头明确了,下一步就清晰了
第四步:按来源方向针对性排查
确认方向后,直奔最常见根因:
-
后端发 RST:查它是否 OOM 被杀(
dmesg | grep -i "killed process")、文件描述符满(lsof -p PID | wc -l对比ulimit -n)、空闲超时比 Nginx 短(如 TomcatconnectionTimeout=30s,而 Nginx keepalive 是 60s) -
客户端发 RST:检查前端 AJAX 是否未调用
abort()就跳页、小程序是否退后台被系统回收网络、移动端是否频繁切换 Wi-Fi/4G -
中间设备发 RST:查云厂商 SLB 默认空闲超时(常为 60–300 秒),对比 Nginx
keepalive_timeout和后端配置;企业防火墙 conntrack 老化策略也常静默踢掉长连接


















