网络错误排查(一):连接超时、DNS解析失败、SSL/TLS证书问题

做SDK接入,网络错误是排查的大头。我见过不少团队,日志都没看全就开始改代码,结果折腾两天发现是DNS缓存没刷新。今天咱们专攻三类最常见的网络错误:连接超时、DNS解析失败、SSL/TLS证书问题。把这三种搞清楚,至少能覆盖80%的线上网络报错。

核心原则:遇到网络报错,先区分是“连不上”还是“连上了但验证失败”。超时和DNS属于前者,证书问题属于后者。排查工具完全不同。

一、连接超时

连接超时,说白了就是客户端发起了握手,但服务端在规定时间内没给回应。SDK日志里常见Connection timed out或connect() failed: Operation now in progress。为什么会这样?我从三个维度看:

  1. 网络连通性——物理链路断了,比如防火墙拦了、远端服务挂了。
  2. 超时配置不合理——比如Android默认连接超时是10秒,你调成2秒,一个跨洋请求根本不够。
  3. TCP队列满——服务端backlog耗尽,新连接被内核丢弃。

我个人习惯先做两步快速验证:

快速定位技巧:
• 用 curl -o /dev/null -s -w '%{time_total}' https://your-api.com 看实际耗时。
• 用 telnet your-api.com 443 测端口是否开放。
• 抓包:tcpdump -i eth0 host your-api.com 看SYN包有没有收到SYN-ACK。

曾经有个项目,SDK在海外一直报超时。我用curl测延迟300ms,但客户端配的是3秒超时——按理说够用。后来抓包发现,移动网络下TCP握手的RTT平均600ms,加上TLS协商的往返,总耗时超过3秒。解决方案很简单:把超时时间提高到8秒,同时加了重试机制。

场景 常见原因 建议操作
偶发超时 网络抖动、丢包 加指数退避重试,最多3次
持续超时 防火墙/DNS错误/服务挂了 抓包确认SYN是否出得去
Android/iOS差异 系统代理设置、VPN 检查ProxySelector,绕过直连

二、DNS解析失败

DNS解析失败,日志里通常长这样:Unable to resolve host "api.example.com": No address associated with hostname。嗯,这里要注意:DNS问题不一定是配置写错了,很多时候是缓存污染或DNS服务器本身故障。

我遇到过最坑的一次:某个SDK在部分华为手机上间歇性无法解析。查了一圈发现,那些手机启用了“智能DNS加速”,把域名解析结果缓存了10分钟,而我们刚好做过域名切换,旧IP早已失效。解决方案是设置TTL=0强制不缓存——虽然性能差点,但保正确。

警告:不要在SDK里写死IP地址!你想想看,一旦服务端做CDN切换或IP轮换,你的App就废了。永远使用域名,并依赖系统的DNS解析。

排查DNS问题的三步走:

  • 第一步:用nslookup api.example.com或dig api.example.com查解析结果。如果本地能解,但App里不行,说明是SDK或系统配置层面的问题。
  • 第二步:检查代理设置。很多企业网络会用代理DNS,导致解析结果跟公网不一致。SDK里要能设置是否走系统代理。
  • 第三步:使用getaddrinfo()的线程安全调用。我们生产环境就遇到过多线程并发解析时,libc的gethostbyname()返回空,改用getaddrinfo后解决。

三、SSL/TLS证书问题

证书错误最让人头大。日志里常见javax.net.ssl.SSLHandshakeException、certificate expired、hostname in certificate didn't match。其实核心就三类:

  1. 证书过期——服务端忘记续费了。
  2. 域名不匹——证书里绑定的域名跟你实际访问的不一致。
  3. 根证书缺失——老旧Android版本没有Let's Encrypt的根证书。

我记得有一次配合客户排查,他那边报CertPathValidatorException: Trust anchor for certification path not found。我让他用openssl s_client -connect api.example.com:443 -servername api.example.com查看证书链,结果发现服务端只发了叶子证书,没发中间证书。浏览器能正常访问是因为浏览器缓存了中间证书,但SDK的SSL context没有。解决方案:服务端把中间证书补全。

检查SSL证书的常用命令:
openssl s_client -connect your-api.com:443 -servername your-api.com 2>/dev/null | openssl x509 -text
用这个能看到证书有效期、签发者、subject、SAN等。

另一个常见坑:SNI。如果你的SDK跑在Java 6上,默认不支持SNI,而服务端配置了多域名HTTPS,那么握手直接就断了。升级TLS版本或手动设置SNI扩展就可以。

本章知识体系

下面这张图把三类网络错误的关键点、排查手段和典型场景串起来了。你可以打印出来贴墙上。

网络错误排查核心逻辑 网络报错 连接超时 常见场景 • 防火墙拦截 • 超时配置过短 • TCP队列满 DNS解析失败 常见场景 • 缓存污染 • DNS服务器故障 • 代理DNS不一致 SSL/TLS证书问题 常见场景 • 证书过期 • 域名不匹配 • 中间证书缺失 通用排查工具 curl | tcpdump | nslookup/dig | openssl s_client
避坑指南:我曾经花了一下午调试一个SSL错误,最后发现是系统时间不对(手机设置成了2000年)。用openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt certificate.pem时记得先校准设备时间。

总结一下,网络错误排查没有那么玄乎。你只要记住:先确认物理可达 → 再确认DNS → 最后确认证书,每一步都有现成的命令行工具。下次SDK报网络错,别急着翻代码,先跑几个命令看看,效率会高很多。