网络问题排查
场景
线上用户反馈接口加载慢或请求失败率升高,需要定位并修复网络层问题。
排查与方案
1. 分层排查
2. OkHttp 日志拦截
// 添加 EventListener 监控每个阶段耗时
class NetworkEventListener : EventListener() {
private var callStart = 0L
override fun callStart(call: Call) { callStart = now() }
override fun dnsStart(call: Call, domainName: String) { log("DNS start") }
override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>) {
log("DNS: ${now() - callStart}ms")
}
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) {
log("Connect start")
}
override fun secureConnectEnd(call: Call, handshake: Handshake?) {
log("TLS: ${now() - callStart}ms")
}
override fun responseBodyEnd(call: Call, byteCount: Long) {
log("Total: ${now() - callStart}ms, body: ${byteCount}B")
}
}
3. 常见问题与方案
| 问题 | 排查方式 | 解决方案 |
|---|---|---|
| DNS 解析慢 | EventListener dnsEnd - dnsStart | HTTPDNS / 预解析 |
| TLS 握手慢 | secureConnectEnd 耗时 | TLS 1.3 / Session 复用 |
| 弱网请求超时 | 特定网络类型失败率高 | 动态超时 + 重试策略 |
| 大 JSON 解析慢 | Profiler CPU | 流式解析 / Protobuf |
| 服务端慢 | 对比 responseHeaderEnd 和 callStart | 后端优化 / CDN |
// 弱网自适应超时
val client = OkHttpClient.Builder()
.connectTimeout(
if (NetworkUtil.isWeak()) 30L else 10L,
TimeUnit.SECONDS
)
.addInterceptor(RetryInterceptor(maxRetry = 3))
.build()
面试答题要点
- 使用 OkHttp
EventListener精确定位各阶段耗时 - DNS 慢 → HTTPDNS;TLS 慢 → 1.3 + Session Ticket
- 弱网场景的兜底策略(重试、降级、离线缓存)
- 关键接口用 Protobuf 替代 JSON 减少传输和解析时间