OkHttp 架构设计详解
一、整体架构总览
OkHttp 的核心设计可以用一张分层图来概括:
┌─────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ OkHttpClient / Request / Response │
├─────────────────────────────────────────────────────┤
│ 调度层 (Dispatcher) │
│ 同步执行 / 异步线程池调度 │
├─────────────────────────────────────────────────────┤
│ 拦截器链 (Interceptor Chain) │
│ ┌───────────────────────────────────────────────┐ │
│ │ RetryAndFollowUpInterceptor (重试与重定向) │ │
│ │ BridgeInterceptor (桥接/请求头补全) │ │
│ │ CacheInterceptor (缓存) │ │
│ │ ConnectInterceptor (连接) │ │
│ │ CallServerInterceptor (网络请求执行) │ │
│ └───────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────┤
│ 连接层 (Connection) │
│ ConnectionPool / RealConnection / Route │
├─────────────────────────────────────────────────────┤
│ I/O 层 (Okio) │
│ Source / Sink / Buffer │
└─────────────────────────────────────────────────────┘
二、核心组件
1. OkHttpClient — 全局配置中心
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor) // 应用拦截器
.addNetworkInterceptor(networkInterceptor) // 网络拦截器
.connectionPool(new ConnectionPool())
.cache(new Cache(cacheDir, cacheSize))
.dns(Dns.SYSTEM)
.build();
设计原则:一个应用只需创建一个实例(单例),内部共享连接池、线程池、缓存。
2. Request & Response — 不可变数据对象
// Request: 不可变,描述"要做什么"
Request request = new Request.Builder()
.url("https://api.example.com/data")
.header("Authorization", "Bearer token")
.post(requestBody)
.build();
// Response: 不可变头部 + 一次性消费的 body
Response response = client.newCall(request).execute();
3. Call — 请求的执行单元
┌──────────────┐
│ Call (接口) │
└──────┬───────┘
│
┌──────▼───────┐
│ RealCall │ ← 实际实现
└──────┬───────┘
│
┌───────┴────────┐
│ │
execute() enqueue()
(同步) (异步)
// 同步
Response response = client.newCall(request).execute();
// 异步
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) { }
@Override public void onResponse(Call call, Response response) { }
});
三、调度器(Dispatcher)— 并发控制
┌──────────────────────────────────────────┐
│ Dispatcher │
├──────────────────────────────────────────┤
│ maxRequests = 64 (最大并发数) │
│ maxRequestsPerHost = 5 (每主机最大并发) │
├──────────────────────────────────────────┤
│ readyAsyncCalls (等待队列) │
│ runningAsyncCalls (执行中-异步) │
│ runningSyncCalls (执行中-同步) │
├──────────────────────────────────────────┤
│ executorService (线程池) │
│ ← CachedThreadPool (核心0,无上限,60s回收) │
└──────────────────────────────────────────┘
调度流程:
enqueue(call)
│
▼
runningAsyncCalls.size < 64 ──── 否 ───→ 放入 readyAsyncCalls
且 sameHost < 5 (等待)
│ 是
▼
放入 runningAsyncCalls
│
▼
executorService.execute(AsyncCall)
│
▼
执行完毕 → 从running移除 → 扫描ready队列 → 提升符合条件的call
四、拦截器链(核心设计)— 责任链模式
这是 OkHttp 最精髓的设计。
整体链路
用户自定义应用拦截器 (Application Interceptors)
│
┌────────────▼────────────┐
│ RetryAndFollowUpInterceptor │ ← 重试 & 重定向 (最多20次)
└────────────┬────────────┘
┌────────────▼────────────┐
│ BridgeInterceptor │ ← 补全请求头 / gzip / Cookie
└────────────┬────────────┘
┌────────────▼────────────┐
│ CacheInterceptor │ ← HTTP 缓存策略
└────────────┬────────────┘
┌────────────▼────────────┐
│ ConnectInterceptor │ ← 建立 TCP/TLS 连接
└────────────┬────────────┘
│
用户自定义网络拦截器 (Network Interceptors)
│
┌────────────▼────────────┐
│ CallServerInterceptor │ ← 真正发送请求,读取响应
└─────────────────────────┘
责任链执行机制
// 核心代码简化
public class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final int index; // 当前执行到哪个拦截器
@Override
public Response proceed(Request request) {
// 创建下一个链节点
RealInterceptorChain next = new RealInterceptorChain(
interceptors, index + 1, request, ...);
// 取出当前拦截器
Interceptor interceptor = interceptors.get(index);
// 调用当前拦截器,传入"下一个链"
Response response = interceptor.intercept(next);
return response;
}
}
intercept(chain) intercept(chain) intercept(chain)
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ Interceptor1 │──proceed()──→│ Interceptor2 │──proceed()──→│ Interceptor3 │
│ │←──response───│ │←──response───│ │
│ 前置处理 │ │ 前置处理 │ │ 实际网络请求 │
│ 后置处理 │ │ 后置处理 │ │ │
└─────────────┘ └─────────────┘ └──────────────┘
各拦截器职责详解
① RetryAndFollowUpInterceptor
请求进入
│
▼
while (true) {
│
├── 创建 ExchangeFinder (寻找可用连接)
│
├── 调用 chain.proceed(request)
│ │
│ ├── 成功 → 检查是否需要重定向 (301/302/307/308)
│ │ ├── 是 → followUpRequest, 重定向次数 < 20? → 继续循环
│ │ └── 否 → 返回 response
│ │
│ └── 异常 → 判断是否可以恢复
│ ├── 连接未建立 / 幂等请求 → 重试
│ └── 不可恢复 → 抛出异常
│
}
② BridgeInterceptor
请求方向 (补全请求头):
┌─────────────────────────────────────┐
│ Content-Type (根据 RequestBody) │
│ Content-Length (根据 RequestBody) │
│ Host (从 URL 提取) │
│ Connection: Keep-Alive │
│ Accept-Encoding: gzip │
│ Cookie (从 CookieJar 读取) │
│ User-Agent: okhttp/4.x.x │
└─────────────────────────────────────┘
响应方向 (解压缩):
如果响应是 gzip → 用 GzipSource 解压 → 移除 Content-Encoding/Content-Length
③ CacheInterceptor
请求进入
│
▼
从 Cache 中查找候选响应 (cacheCandidate)
│
▼
CacheStrategy.Factory 计算策略
│
├── networkRequest = null, cacheResponse = null
│ → 返回 504 (强制缓存但无缓存)
│
├── networkRequest = null, cacheResponse != null
│ → 直接返回缓存 (强缓存命中, Cache-Control: max-age)
│
├── networkRequest != null, cacheResponse = null
│ → 走网络
│
└── networkRequest != null, cacheResponse != null
→ 条件请求 (If-None-Match / If-Modified-Since)
→ 网络返回 304 → 合并缓存头部返回
→ 网络返回 200 → 更新缓存,返回新响应
④ ConnectInterceptor
// 核心:找到或创建一个可用连接
override fun intercept(chain: Chain): Response {
val exchange = chain.call.initExchange(chain) // 关键!
return chain.proceed(request)
}
initExchange()
│
▼
ExchangeFinder.findHealthyConnection()
│
├── 1. 尝试复用当前 Call 已有的连接
├── 2. 从 ConnectionPool 中查找可复用连接
├── 3. 切换路由再从 Pool 查找
└── 4. 创建新连接 (TCP握手 + TLS握手)
│
▼
放入 ConnectionPool
⑤ CallServerInterceptor
写入请求头 (HTTP/1.1 或 HTTP/2 帧)
│
▼
写入请求体 (POST/PUT)
├── 普通写入
└── Expect: 100-continue → 等服务器确认再发body
│
▼
刷新输出流 (flush)
│
▼
读取响应头
│
▼
构建 Response (包装响应体为延迟读取的 Source)
│
▼
返回 Response
五、连接管理
1. ConnectionPool(连接池)
┌─────────────────────────────────────────┐
│ ConnectionPool │
├─────────────────────────────────────────┤
│ maxIdleConnections = 5 │
│ keepAliveDuration = 5 minutes │
├─────────────────────────────────────────┤
│ connections: ConcurrentDeque<Connection>│
├─────────────────────────────────────────┤
│ cleanupRunnable (后台清理线程) │
│ ← 定期扫描,清理超过keepAlive的空闲连接 │
│ ← 清理超过maxIdle的多余空闲连接 │
└─────────────────────────────────────────┘
2. 连接复用机制
新请求到来
│
▼
遍历 ConnectionPool
│
├── 匹配条件:
│ ✓ 相同 host + port
│ ✓ 连接未关闭
│ ✓ 未超过最大并发流 (HTTP/2 可多路复用)
│ ✓ TLS 证书匹配
│
├── 命中 → 复用连接 (避免 TCP+TLS 握手开销)
│
└── 未命中 → 新建连接 → 放回池中
3. 连接建立流程
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ DNS │────→│ TCP 握手 │────→│ TLS 握手 │────→│ HTTP │
│ 解析 │ │ (3次握手) │ │(如果HTTPS)│ │ 请求/响应 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
▼ ▼
支持自定义DNS 支持证书锁定 (CertificatePinner)
(实现Dns接口) 支持自定义TrustManager
六、HTTP/2 支持
┌─────────────────────────────────────────┐
│ HTTP/2 多路复用 │
├─────────────────────────────────────────┤
│ │
│ 一个 TCP 连接 ─┬─ Stream 1 (请求A) │
│ ├─ Stream 2 (请求B) │
│ ├─ Stream 3 (请求C) │
│ └─ Stream N ... │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ HEADERS │ │ DATA │ │SETTINGS │ │
│ │ Frame │ │ Frame │ │ Frame │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ Http2Connection │
│ ├── Http2Writer (发送帧) │
│ ├── Http2Reader (读取帧) │
│ ├── streams: Map<Int, Http2Stream> │
│ └── settings (流控/窗口大小) │
└─────────────────────────────────────────┘
七、缓存架构
┌────────────────────────────────────────────┐
│ Cache │
├────────────────────────────────────────────┤
│ 底层: DiskLruCache │
│ ├── Key = MD5(request.url) │
│ ├── Entry.0 = 响应头 (metadata) │
│ └── Entry.1 = 响应体 (body) │
├────────────────────────────────────────────┤
│ 缓存策略判断 (HTTP RFC 7234): │
│ ├── Cache-Control: max-age, no-cache... │
│ ├── Expires │
│ ├── ETag → If-None-Match │
│ ├── Last-Modified → If-Modified-Since │
│ └── Age, Vary 等 │
└────────────────────────────────────────────┘
八、完整请求流程图
client.newCall(request).enqueue(callback)
│
▼
┌─────────────────┐
│ Dispatcher │ ← 判断并发数,决定立即执行还是入队
│ 调度 │
└───────┬─────────┘
│ 线程池执行
▼
┌─────────────────┐
│ getResponseWith │ ← 构建拦截器列表
│ InterceptorChain │
└───────┬─────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Interceptor Chain │
│ │
│ [用户应用拦截器] │
│ ↓ │
│ RetryAndFollowUpInterceptor │
│ ↓ ↑ 重试/重定向 │
│ BridgeInterceptor │
│ ↓ 补全请求头 ↑ gzip解压 │
│ CacheInterceptor │
│ ↓ ↑ 写入缓存 │
│ ┌──┴──────┐ │
│ │有缓存命中│→ 直接返回 │
│ │无缓存 │ │
│ └──┬──────┘ │
│ ConnectInterceptor │
│ ↓ 获取/创建连接 │
│ [用户网络拦截器] │
│ ↓ │
│ CallServerInterceptor │
│ ↓ 写请求 ↑ 读响应 │
│ ═══════════════════════════════════════════ │
│ Network (Socket I/O via Okio) │
└─────────────────────────────────────────────────┘
│
▼
回调 Callback.onResponse / onFailure
九、核心设计模式总结
| 设计模式 | 应用位置 | 说明 |
|---|---|---|
| 责任链模式 | Interceptor Chain | 最核心设计,请求逐层传递 |
| 建造者模式 | OkHttpClient.Builder / Request.Builder | 复杂对象的构建 |
| 工厂模式 | Call.Factory (OkHttpClient实现) | 创建 Call 对象 |
| 策略模式 | CacheStrategy | 缓存策略的计算 |
| 享元模式 | ConnectionPool | 连接的复用与共享 |
| 观察者模式 | EventListener | 监听请求生命周期事件 |
| 外观模式 | OkHttpClient | 对外统一入口 |
| 不可变对象 | Request / Response / Headers | 线程安全 |
十、应用拦截器 vs 网络拦截器
Application Network
Interceptor Interceptor
│ │
位置 最外层 ConnectInterceptor之后
是否看到重定向响应 × ✓ (每次网络调用都触发)
是否看到重试 × ✓
缓存命中时是否执行 ✓ × (短路,不走网络)
看到原始请求 ✓ (用户原始) × (已被Bridge补全)
可修改最终请求头 × ✓
典型用途 日志/统一参数/Token 流量监控/修改响应头
// 应用拦截器:无论缓存命中与否都执行
client.addInterceptor(chain -> {
Request req = chain.request().newBuilder()
.header("Token", getToken())
.build();
long t1 = System.nanoTime();
Response response = chain.proceed(req);
long t2 = System.nanoTime();
Log.d("耗时: " + (t2 - t1) / 1e6 + "ms");
return response;
});
// 网络拦截器:只在真正网络请求时执行
client.addNetworkInterceptor(chain -> {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.header("Cache-Control", "max-age=60")
.build();
});
十一、EventListener — 全链路监控
public abstract class EventListener {
callStart()
│
dnsStart() → dnsEnd() // DNS 解析
│
connectStart() // 连接开始
├── secureConnectStart() → secureConnectEnd() // TLS
connectEnd() // 连接结束
│
connectionAcquired() // 获得连接
│
requestHeadersStart() → requestHeadersEnd()
requestBodyStart() → requestBodyEnd()
│
responseHeadersStart() → responseHeadersEnd()
responseBodyStart() → responseBodyEnd()
│
connectionReleased() // 释放连接
│
callEnd() / callFailed()
}
十二、关键源码类导航
okhttp3/
├── OkHttpClient.kt ← 配置中心 + Call.Factory
├── Request.kt ← 请求模型
├── Response.kt ← 响应模型
├── Call.kt ← 接口
├── RealCall.kt ← Call 实现,构建拦截器链
├── Dispatcher.kt ← 调度器
├── Cache.kt ← 缓存(基于DiskLruCache)
│
├── internal/connection/
│ ├── RealConnectionPool.kt ← 连接池实现
│ ├── RealConnection.kt ← TCP/TLS 连接
│ ├── Exchange.kt ← 单次请求-响应交换
│ └── ExchangeFinder.kt ← 查找/创建可用连接
│
├── internal/http/
│ ├── RetryAndFollowUpInterceptor.kt
│ ├── BridgeInterceptor.kt
│ ├── CacheInterceptor.kt
│ ├── ConnectInterceptor.kt
│ ├── CallServerInterceptor.kt
│ └── RealInterceptorChain.kt ← 责任链实现
│
└── internal/http2/
├── Http2Connection.kt ← HTTP/2 连接管理
└── Http2Stream.kt ← HTTP/2 流
总结
OkHttp 架构设计的三大核心思想:
-
拦截器责任链 — 将复杂的 HTTP 处理拆解为独立、可组合、可扩展的拦截器,每个拦截器只关注单一职责,用户可以在链条的不同位置插入自定义逻辑
-
连接复用 — 通过 ConnectionPool 实现 TCP/TLS 连接的缓存与复用,结合 HTTP/2 多路复用,极大降低了网络延迟和资源消耗
-
分层解耦 — 应用层(Request/Response)→ 调度层(Dispatcher)→ 协议层(Interceptors)→ 连接层(Connection)→ I/O 层(Okio),每层职责清晰,互不依赖