strace -f -e trace=network 发现大量 connect/reset 的业务层排查

9次阅读

大量 connect() 后紧接 close() 或 sendto() 失败,主因是业务逻辑或中间件配置异常;需排查连接发起方、断开原因及重试控制,检查目标地址、端口、连接池配置、服务状态及客户端库策略。

strace -f -e trace=network 发现大量 connect/reset 的业务层排查

strace -f -e trace.network 显示大量 connect() 调用后紧跟着 close()sendto() 失败(如 ECONNRESETECONNREFUSED),通常不是内核或网络设备问题,而是业务逻辑或中间件配置异常导致的主动/被动连接中断。排查需聚焦在「谁发起连接」「为何立刻断开」「是否重试失控」三个层面。

确认连接发起方和目标地址

strace 输出中每条 connect( sockfd, {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("10.20.30.40")}, ...) 都包含目标 IP 和端口。重点关注:

  • 目标地址是否为预期服务(如本该连本地 redis 却连了已下线的旧集群 IP)
  • 端口是否匹配实际服务监听端口(如应用配了 6379,但 redis 实际启在 6380)
  • 同一进程是否高频重复连接同一地址(比如循环里 new client 未复用)

检查连接建立后的行为模式

观察 strace 中 connect() 后是否立即出现 write()/sendto() + ECONNRESET,或 close() 调用:

  • 成功 connect 后立刻 send 失败:大概率远端服务拒绝请求(协议不匹配、认证失败、连接数超限),可抓包验证服务端响应
  • connect 成功后立即 close:常见于连接池未命中时新建连接又因超时/条件不满足被丢弃,需查连接池配置(如 maxIdle=0、minIdle=0 导致无复用)
  • connect 返回 ECONNREFUSED:目标端口无进程监听,或防火墙拦截,优先检查服务是否存活、端口监听状态(ss -tlnp | grep :port

定位触发连接的业务代码路径

strace 的 -f 会显示子进程/线程,结合 -p PID-e trace=network,process 可关联系统调用与进程树。更高效方式是:

  • lsof -i -p $PID 查看当前所有 socket 连接状态,比对 strace 中异常连接是否持续存在
  • 在应用层开启 debug 日志(如 java-Djavax.net.debug=ssl:handshakehttp 客户端日志),定位哪段业务代码触发连接
  • 检查是否有定时任务、健康检查探针、或异常兜底逻辑(如降级时疯狂重试不可用服务)

排除中间件与客户端库行为

很多连接重置源于客户端库的默认策略:

  • HTTP 客户端(如 okhttpapache HttpClient)默认启用 keep-alive,但服务端关闭连接后,客户端可能未及时清理连接池中的失效连接
  • 数据库/Redis 客户端若配置了过短的 timeout(如 connectTimeout=100ms),在网络抖动时大量新建连接并快速失败
  • gRPC 客户端若未配置合理的 keep-alive 参数,在长连接空闲后被服务端断开,客户端重连时出现 burst
text=ZqhQzanResources