系统学习 故障排查学习路径:从方法论到系统、网络、数据库与 K8s

connection-reset-by-peer

连接被对端重置(connection reset by peer)的定位与修复

现象

客户端报 read: connection reset by peer、Connection reset by peer、ECONNRESET,Go 程序还可能看到 unexpected EOF,写操作则可能报 broken pipe。它和 Connection refused、连接超时都不同:refused 是目标端口没有监听或被明确拒绝,超时是数据包被静默丢弃,而 RST 表示对端或中间设备主动发送了重置包。

RST 可能发生在 TLS 握手、请求发送、等待响应或空闲连接复用时。定位的关键不是只看报错文本,而是确认“谁发的 RST、发生在哪个阶段、当时连接处于什么状态”。

快速定位

先复现并观察连接状态:

curl -v --no-keepalive https://<host>/
curl -v https://<host>/ https://<host>/ https://<host>/
ss -tin state established '( dport = :<port> or sport = :<port> )'

抓包确认 RST 的来源和阶段:

tcpdump -ni any -vvv 'host <host> and port <port>'
nstat -az | grep -i -E 'reset|abort|overflow|drop'
journalctl -u <service> --since '30 min ago'
dmesg -T | tail -50

Kubernetes 场景同时看副本重启和端点变化:

kubectl get pod -n <ns> -o wide
kubectl describe pod <pod> -n <ns>
kubectl logs <pod> -n <ns> --previous
kubectl get endpointslice -n <ns> -o wide
kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -30

NAT 或负载均衡场景检查会话表:

conntrack -S
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
sysctl net.ipv4.tcp_abort_on_overflow

tcpdump 里看 RST 的源地址:源是服务端,说明服务进程、内核队列或服务端防火墙主动重置;源是客户端,则可能是客户端超时放弃、连接池关闭或客户端侧设备拦截。如果单次新建连接正常、连续请求或等待一段时间后失败,重点查连接复用和超时;如果每次建连都失败,重点查协议、端口和中间设备。抓包时同时记录两端时间,避免时钟偏差造成误判。

常见根因

  1. 服务进程崩溃、被 OOM 杀死或重启,内核在关闭仍有未读数据的连接时发送 RST。
  2. 空闲超时不匹配:负载均衡、NAT、Nginx 或服务端的空闲时间短于客户端连接池的复用时间,客户端复用已关闭的连接。
  3. 服务端主动拒绝:连接数上限、限流、协议错误、把 TLS 流量发到明文端口,或把 HTTP 发到 HTTPS 端口。
  4. accept 队列溢出。tcp_abort_on_overflow=1 时内核直接回 RST;为 0 时通常表现为丢包和超时。
  5. conntrack 表满或会话过期,NAT 映射失效,后续包被重置或丢弃。
  6. 防火墙或安全组使用 REJECT --reject-with tcp-reset,或云防火墙会话超时后重置连接。
  7. Kubernetes 滚动更新时 Pod 正在终止,但端点摘除有延迟;没有 preStop 或优雅关闭不完整。
  8. gRPC/HTTP2 长连接遇到 GOAWAY、keepalive 超时或服务端最大连接年龄时,客户端通常先表现为 UNAVAILABLE 或 transport closing;只有宽限期结束后被强制断开,才可能看到连接重置。
  9. 应用层半关闭后仍继续写入,出现 broken pipe,随后连接被重置。
  10. 中间设备(IPS、代理、云 LB)因策略或资源问题注入 RST。
  11. 服务端设置 SO_LINGER 为 0,或关闭连接前丢弃接收缓冲区,主动发送 RST 而不是正常 FIN。

修复

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. connection reset by peer 与 connection refused、连接超时的本质区别是什么?
  2. 空闲一段时间后的第一个请求失败、重试后恢复,最可能是什么原因?
  3. 如何确认 RST 是谁发出的,以及它发生在哪个阶段?
答案
  1. RST 表示对端或中间设备主动重置了连接;refused 表示目标端口没有监听或被明确拒绝;超时表示数据包被静默丢弃或路径不通。
  2. 客户端连接池复用了已被服务端、负载均衡或 NAT 关闭的空闲连接。应让客户端最大空闲时间小于服务端和 LB 的空闲超时,并配合 keepalive、连接健康检查和幂等重试。
  3. 用 tcpdump -vvv 看 RST 的源地址、TCP 标志和时间点,结合 ss -tin 的队列/重传状态、nstat 计数以及服务端日志,判断是握手、请求、响应还是空闲阶段。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令