“104: Connection reset by peer”本质是Linux内核返回的ECONNRESET错误,表示本端读写时对端已通过TCP RST报文强制终止连接,需抓包确认RST发出方(客户端、服务端或中间设备),并排查后端连接管理、协议头超限、健康检查干扰、防火墙conntrack老化及连接池生命周期不匹配等问题。

“104: Connection reset by peer”本质是 Linux 内核返回的 ECONNRESET 错误,表示本端尝试读写时,对端已通过 TCP RST 报文强制终止连接。它不是超时或拒绝连接,而是明确的“被对方主动掐断”。排查需从连接生命周期入手,聚焦谁发了 RST、为何发、何时发。
确认 RST 的实际发出方
仅看日志无法判断 RST 来自客户端、服务端,还是中间设备(如 LB、防火墙、API 网关)。必须抓包验证:
- 在报错服务所在机器上用
tcpdump -i any 'host and port '捕获双向流量 - 过滤出含
[R.], ack或[R]标志的 TCP 包,查看其源 IP —— 若源是后端服务 IP,说明后端主动重置;若是负载均衡器 IP,问题大概率出在 LB 健康检查或会话策略;若源是客户端公网 IP,需检查客户端行为或本地出口网关 - 特别注意:Nginx 日志中
recv() failed (104...)通常意味着 RST 来自 upstream(后端),而readv() failed...多指向客户端侧中断
检查后端服务的连接管理逻辑
服务端主动发 RST 的常见场景包括:
- 连接未正确关闭:例如 Tomcat 接收完请求但未等响应写完就调用了 close();Node.js 中 socket.destroy() 被误用而非 socket.end()
-
请求头/体超限被静默拒绝:Nginx 默认
client_header_buffer_size为 1k,若后端(如 Spring Boot)配置了更大的max-http-header-size,而 Nginx 转发时 header 超长,部分后端容器(如旧版 Tomcat)不返回 4xx,直接 RST - 健康检查干扰:使用 TCP 层探活(非 HTTP)时,某些后端(如 IIS、部分嵌入式服务)在空闲连接超时后发 RST 而非 FIN,导致代理层复用该连接时触发 104
审查中间网络设备策略
很多 RST 并非业务服务所为,而是基础设施拦截:
- 云厂商 SLB/ALB 的四层健康检查若配置为 TCP 握手即成功,且未及时断连,后端服务超时后可能 RST 回应,被代理误认为业务异常
- 防火墙或安全组启用连接跟踪(conntrack),对长时间空闲连接(尤其无 keepalive)执行老化(aging out),清理时向两端发 RST
- K8s Service 的 kube-proxy 在 iptables 模式下,若 endpoint 异常消失而 conntrack 表未及时刷新,后续包可能被丢弃并触发 RST
验证系统与内核层面限制
资源不足或内核参数不当会间接导致 RST:
- 检查
netstat -s | grep -i "reset",观察connections reset due to unexpected data或connections reset due to early user close计数是否突增 - 确认
net.ipv4.tcp_fin_timeout(默认 60 秒)和net.ipv4.ip_local_port_range是否合理,短连接高峰时端口耗尽会导致新 SYN 被 RST - 应用若使用连接池(如 HikariCP、Apache HttpClient),需核对
maxLifetime与后端wait_timeout关系——连接池维持的空闲连接若超过数据库自动断连阈值,首次复用即 RST

















