connection reset by peer本质是tcp层rst包强制断连,需先通过curl和日志定位故障端(客户端/中间链路/服务端),再抓包确认rst源ip,结合ss、netstat检查连接队列与资源限制,最后绕过中间件直连验证并核查nginx等代理配置。
立即进入“夸克ai手把手教你,操作像呼吸一样简单!☜☜☜☜☜点击进入”;
当你在服务日志里看到Connection reset by peer或浏览器报net::ERR_CONNECTION_RESET,说明TCP连接在数据传输阶段被对端强制中断,不是正常断开,而是对方直接发了RST包——这一步操作不可逆,且不等待你发完数据。
先确认错误出现在哪一端
打开终端,执行:curl -v https://api.ipify.org?format=json。如果返回Failed to connect to api.ipify.org port 443: Connection reset by peer,说明问题在客户端侧或中间链路;如果curl成功但你的应用日志里持续报错,那问题大概率在服务端或其上游组件。
注意:不要跳过这一步直接改代码——很多团队花两天调HTTP超时参数,结果发现是WAF把PUT请求全拦了。
查服务端access日志有没有记录
进入服务日志目录,运行:tail -f ./log/access.log | grep -E "(502|reset|refused)"。
如果一条日志都没有,说明请求根本没进到Web服务器(如Nginx、Tomcat),可能卡在负载均衡器、安全组、WAF或防火墙;如果能看到502 Bad Gateway,说明反向代理收到了响应但后端已断连;如果日志里有完整200但客户端仍报reset,那问题出在客户端网络或浏览器扩展。
抓包看RST到底谁发的
方法一:在服务端执行:/usr/sbin/tcpdump -i eth0 -n -nn 'tcp[tcpflags] & (tcp-rst) != 0 and host 10.20.30.40' -w reset.pcap(把10.20.30.40换成客户端真实IP)。
方法二:在客户端用Chrome开发者工具→Network→右键请求→Save as HAR with content,然后用Wireshark打开HAR里的原始请求做比对。
【关键判断点】如果tcpdump捕获到服务端IP主动发出RST包,且时间戳紧贴客户端SYN-ACK之后、HTTP请求发送之前,基本可锁定是服务端socket未及时accept导致连接队列溢出,或进程已崩溃但端口仍监听。
检查系统连接队列和资源水位
第一步:查看已完成连接队列是否堆积:ss -lnt | grep :8080,观察Recv-Q列数值。若长期大于0,说明accept()调用跟不上新连接速度。
第二步:检查文件描述符限制:cat /proc/$(pgrep -f 'java.*Application')/limits | grep "Max open files",对比ulimit -n输出。若软限制远低于硬限制,且日志出现Too many open files,立刻调整。
第三步:确认TIME_WAIT连接是否占满端口:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'。若TIME_WAIT超过65535,需调优net.ipv4.tcp_tw_reuse并确认客户端是否用了短连接风暴式请求。
绕过中间件直连验证
停掉Nginx,用curl http://127.0.0.1:8080/health直连后端服务。如果直连成功,问题一定出在Nginx、云厂商SLB或WAF上。
重点检查Nginx配置中proxy_next_upstream error timeout http_502是否漏配,以及keepalive_timeout是否设为0——某些旧版Nginx设0会导致它对后端用短连接,而业务服务又没配maxKeepAliveRequests,连接复用断裂瞬间就触发RST。











