graph TB
A[应用层] --> B[OkHttpClient]
B --> C[Request Builder]
B --> D[Call Factory]
D --> E[RealCall]
E --> F[Dispatcher]
F --> G[拦截器链]
G --> H[网络层]
subgraph "拦截器链"
I[应用拦截器]
J[重试拦截器]
K[桥接拦截器]
L[缓存拦截器]
M[连接拦截器]
N[网络拦截器]
O[服务器调用拦截器]
end
G --> I
I --> J
J --> K
K --> L
L --> M
M --> N
N --> O
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
final Dispatcher dispatcher;
final @Nullable Proxy proxy;
final List<Protocol> protocols;
final List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors;
final List<Interceptor> networkInterceptors;
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;
final CookieJar cookieJar;
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
final SocketFactory socketFactory;
final SSLSocketFactory sslSocketFactory;
final ConnectionPool connectionPool;
// ... 更多配置项
}
flowchart TD
A[开始创建OkHttpClient] --> B{使用方式}
B -->|默认构造| C[new OkHttpClient]
B -->|Builder模式| D[new OkHttpClient.Builder]
C --> E[使用默认配置]
D --> F[配置各种参数]
E --> G[创建默认组件]
F --> H[验证配置参数]
G --> I[初始化Dispatcher]
H --> I
I --> J[初始化ConnectionPool]
J --> K[初始化SSL配置]
K --> L[初始化拦截器链]
L --> M[初始化缓存配置]
M --> N[初始化超时配置]
N --> O[初始化事件监听器]
O --> P[创建OkHttpClient实例]
P --> Q[客户端就绪]
style C fill:#e3f2fd
style D fill:#f3e5f5
style G fill:#e8f5e8
style H fill:#fff3e0
style Q fill:#c8e6c9
3.1.2 Builder模式原理
OkHttpClient采用Builder模式的主要原因:
参数众多:OkHttpClient有30+个配置参数
可选配置:大部分参数都有合理的默认值
不可变性:创建后的OkHttpClient实例不可修改
链式调用:提供流畅的API体验
参数验证:在build()时统一验证参数合法性
3.1.3 Builder配置流程图
sequenceDiagram
participant App as 应用代码
participant Builder as OkHttpClient.Builder
participant Validator as 参数验证器
participant Factory as 组件工厂
participant Client as OkHttpClient
App->>Builder: new Builder()
Builder->>Builder: 初始化默认配置
loop 配置各种参数
App->>Builder: 设置配置项
Builder->>Builder: 存储配置值
end
App->>Builder: build()
Builder->>Validator: 验证配置参数
alt 参数无效
Validator-->>Builder: 抛出异常
Builder-->>App: 配置异常
else 参数有效
Validator-->>Builder: 验证通过
Builder->>Factory: 创建组件实例
Factory-->>Builder: 返回组件
Builder->>Client: new OkHttpClient(builder)
Client->>Client: 复制Builder配置
Client-->>Builder: OkHttpClient实例
Builder-->>App: 返回客户端
end
3.1.4 超时配置关系图
在创建对象时,连接超时,读取超时,写入超时,完整请求超时,都可以灵活配置。那么这块是如何设计的呢?
graph TB
A[超时配置] --> B[callTimeout]
A --> C[connectTimeout]
A --> D[readTimeout]
A --> E[writeTimeout]
A --> F[pingInterval]
B --> G[整个请求的总超时时间]
C --> H[TCP连接建立超时]
D --> I[从服务器读取数据超时]
E --> J[向服务器写入数据超时]
F --> K[HTTP/2连接保活间隔]
G --> L[包含连接、读写、重定向等所有时间]
H --> M[默认10秒]
I --> N[默认10秒]
J --> O[默认10秒]
K --> P[默认0-不发送ping]
style A fill:#e3f2fd
style B fill:#ffebee
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#f3e5f5
style F fill:#e1f5fe
3.2 Request请求封装
主要是封装一个Request请求体。
java复制代码
Request request = new Request.Builder()
.url(url)
.addHeader("cookie","yangchong")
.get()
.build();
Request类封装了HTTP请求的所有信息:
java复制代码
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Map<Class<?>, Object> tags;
public static class Builder {
@Nullable HttpUrl url;
String method;
Headers.Builder headers;
@Nullable RequestBody body;
Map<Class<?>, Object> tags = Collections.emptyMap();
}
}
graph TB
A[应用调用] --> B{选择执行方式}
B -->|同步| C[call.execute]
B -->|异步| D[call.enqueue]
C --> E[Dispatcher.executed]
D --> F[Dispatcher.enqueue]
E --> G[getResponseWithInterceptorChain]
F --> H[AsyncCall入队]
H --> I[promoteAndExecute]
I --> J[线程池执行AsyncCall]
J --> K[AsyncCall.execute]
K --> G
G --> L[拦截器链处理]
L --> M[网络请求]
M --> N[Response返回]
N --> O{执行方式}
O -->|同步| P[直接返回Response]
O -->|异步| Q[Callback.onResponse]
style C fill:#e1f5fe
style D fill:#f3e5f5
style G fill:#fff3e0
style L fill:#e8f5e8
3.3.3 Execute执行时序图
sequenceDiagram
participant App as 应用代码
participant RealCall as RealCall
participant Transmitter as Transmitter
participant Dispatcher as Dispatcher
participant Chain as InterceptorChain
participant Network as 网络层
App->>RealCall: execute()
Note over RealCall: 1. 检查执行状态
RealCall->>RealCall: synchronized检查executed
alt 已执行
RealCall-->>App: IllegalStateException
end
RealCall->>RealCall: executed = true
Note over RealCall: 2. 超时和生命周期管理
RealCall->>Transmitter: timeoutEnter()
RealCall->>Transmitter: callStart()
Note over RealCall: 3. 调度器管理
RealCall->>Dispatcher: executed(this)
Note over Dispatcher: 添加到runningSyncCalls队列
Note over RealCall: 4. 执行请求
RealCall->>Chain: getResponseWithInterceptorChain()
Chain->>Network: 网络请求处理
Network-->>Chain: Response
Chain-->>RealCall: Response
Note over RealCall: 5. 清理工作
RealCall->>Dispatcher: finished(this)
Note over Dispatcher: 从runningSyncCalls移除
RealCall-->>App: Response
3.3.4 Enqueue执行时序图
sequenceDiagram
participant App as 应用代码
participant RealCall as RealCall
participant Dispatcher as Dispatcher
participant AsyncCall as AsyncCall
participant ThreadPool as 线程池
participant Chain as InterceptorChain
participant Callback as Callback
App->>RealCall: enqueue(callback)
Note over RealCall: 1. 状态检查和设置
RealCall->>RealCall: synchronized检查executed
RealCall->>RealCall: executed = true
Note over RealCall: 2. 创建AsyncCall
RealCall->>AsyncCall: new AsyncCall(callback)
RealCall->>Dispatcher: enqueue(asyncCall)
Note over Dispatcher: 3. 调度逻辑
Dispatcher->>Dispatcher: 添加到readyAsyncCalls
Dispatcher->>Dispatcher: promoteAndExecute()
alt 可以立即执行
Dispatcher->>Dispatcher: 移动到runningAsyncCalls
Dispatcher->>AsyncCall: executeOn(executorService)
AsyncCall->>ThreadPool: execute(this)
Note over ThreadPool: 4. 异步执行
ThreadPool->>AsyncCall: run()
AsyncCall->>AsyncCall: execute()
AsyncCall->>Chain: getResponseWithInterceptorChain()
Chain-->>AsyncCall: Response
Note over AsyncCall: 5. 回调处理
AsyncCall->>Callback: onResponse(call, response)
AsyncCall->>Dispatcher: finished(this)
else 需要等待
Note over Dispatcher: 保持在readyAsyncCalls队列中
end
RealCall-->>App: void (立即返回)
public final class Dispatcher {
private int maxRequests = 64; // 最大并发请求数
private int maxRequestsPerHost = 5; // 单主机最大并发数
// 等待执行的异步请求队列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在执行的异步请求队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
// 正在执行的同步请求队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
}
调度策略:
最大并发请求数限制(默认64个)
单主机最大并发数限制(默认5个)
使用双端队列管理等待和运行中的请求
自动的线程池管理
3.4.1 Dispatcher架构图
graph TB
A[Dispatcher] --> B[ExecutorService]
A --> C[readyAsyncCalls]
A --> D[runningAsyncCalls]
A --> E[runningSyncCalls]
B --> F[ThreadPoolExecutor]
F --> G[核心线程数: 0]
F --> H[最大线程数: Integer.MAX_VALUE]
F --> I[空闲时间: 60秒]
F --> J[队列: SynchronousQueue]
C --> K[等待执行的异步请求]
D --> L[正在执行的异步请求]
E --> M[正在执行的同步请求]
style A fill:#e3f2fd
style B fill:#f3e5f5
style F fill:#e8f5e8
3.4.2 异步调度架构
graph TB
subgraph "Dispatcher异步调度架构"
A[Dispatcher] --> B[ExecutorService]
A --> C[readyAsyncCalls]
A --> D[runningAsyncCalls]
A --> E[runningSyncCalls]
B --> F[ThreadPoolExecutor]
F --> G[核心线程池]
F --> H[最大线程数]
F --> I[队列管理]
subgraph "调度策略"
J[最大并发请求]
K[单主机最大请求]
L[空闲回调]
end
subgraph "请求队列"
C --> M[等待队列]
D --> N[执行队列]
E --> O[同步队列]
end
end
3.4.3 调度策略流程图
flowchart TD
A[AsyncCall入队] --> B[添加到readyAsyncCalls]
B --> C[调用promoteAndExecute]
C --> D{检查执行条件}
D --> E{总请求数 < maxRequests?}
E -->|否| F[保持在ready队列]
E -->|是| G{主机请求数 < maxRequestsPerHost?}
G -->|否| H[继续检查下一个]
G -->|是| I[移动到running队列]
I --> J[callsPerHost计数+1]
J --> K[提交到线程池执行]
K --> L[AsyncCall.execute]
L --> M[执行网络请求]
M --> N[请求完成]
N --> O[调用finished方法]
O --> P[callsPerHost计数-1]
P --> Q[从running队列移除]
Q --> R[再次调用promoteAndExecute]
R --> S[尝试执行ready队列中的请求]
H --> T{还有更多请求?}
T -->|是| D
T -->|否| U[结束本轮调度]
F --> U
S --> U
flowchart TD
A[接收请求] --> B[准备连接]
B --> C{是否被取消?}
C -->|是| D[抛出IOException]
C -->|否| E[执行下一个拦截器]
E --> F{是否发生异常?}
F -->|是| G[调用recover方法]
F -->|否| H[检查响应状态]
G --> I{是否可恢复?}
I -->|是| J[继续重试]
I -->|否| K[抛出异常]
H --> L[调用followUpRequest]
L --> M{需要重定向?}
M -->|否| N[返回响应]
M -->|是| O{重定向次数超限?}
O -->|是| P[抛出ProtocolException]
O -->|否| Q[更新请求]
Q --> R[关闭当前响应]
R --> J
J --> B
style G fill:#ffebee
style I fill:#fff3e0
style M fill:#e8f5e8
style O fill:#fce4ec
3.5.6 缓存拦截器
核心功能
缓存策略:根据HTTP缓存规范决定缓存行为
缓存读取:从缓存中读取有效的响应
缓存写入:将可缓存的响应写入缓存
条件请求:发送If-None-Match、If-Modified-Since等条件请求
flowchart TD
A[接收请求] --> B[从缓存获取候选响应]
B --> C[计算缓存策略]
C --> D{网络请求为null?}
D -->|是| E{缓存响应为null?}
D -->|否| F{缓存响应为null?}
E -->|是| G[返回504错误]
E -->|否| H[返回缓存响应]
F -->|是| I[执行网络请求]
F -->|否| J[执行条件网络请求]
I --> K[获取网络响应]
J --> L[获取网络响应]
K --> M{响应可缓存?}
L --> N{响应状态码?}
N -->|304| O[更新缓存响应]
N -->|其他| P[使用网络响应]
O --> Q[返回更新后的缓存响应]
P --> R{响应可缓存?}
M -->|是| S[写入缓存]
M -->|否| T[返回网络响应]
R -->|是| U[写入缓存]
R -->|否| V[返回网络响应]
S --> T
U --> V
style D fill:#e3f2fd
style E fill:#f3e5f5
style F fill:#e8f5e8
style M fill:#fff3e0
style N fill:#fce4ec
style R fill:#e0f2f1
3.5.7 网络请求拦截器
CallServerInterceptor(网络请求拦截器)
请求发送:将HTTP请求发送到服务器
响应接收:接收服务器的HTTP响应
流控制:管理请求和响应的数据流
协议处理:处理HTTP/1.1和HTTP/2的具体协议细节
sequenceDiagram
participant Chain as RealInterceptorChain
participant CallServer as CallServerInterceptor
participant Exchange as Exchange
participant Codec as ExchangeCodec
participant Connection as RealConnection
participant Server as 服务器
Chain->>CallServer: intercept(chain)
CallServer->>Exchange: writeRequestHeaders(request)
Exchange->>Codec: writeRequestHeaders(request)
Codec->>Connection: 发送请求头
Connection->>Server: HTTP请求头
alt 有请求体
CallServer->>Exchange: createRequestBody(request)
CallServer->>CallServer: 写入请求体数据
CallServer->>Exchange: finishRequest()
Exchange->>Codec: finishRequest()
Codec->>Connection: 发送请求体
Connection->>Server: HTTP请求体
end
CallServer->>Exchange: readResponseHeaders()
Exchange->>Codec: readResponseHeaders()
Codec->>Connection: 读取响应头
Connection->>Server: 请求响应头
Server-->>Connection: HTTP响应头
Connection-->>Codec: 响应头数据
Codec-->>Exchange: 解析后的响应头
Exchange-->>CallServer: Response.Builder
alt 有响应体
CallServer->>Exchange: openResponseBody(response)
Exchange->>Codec: openResponseBodySource(response)
Note over CallServer: 创建响应体Source
end
CallServer-->>Chain: 完整的Response对象
3.5.8 拦截器链状态管理
stateDiagram-v2
[*] --> Created: new RealInterceptorChain()
Created --> Executing: proceed()调用
Executing --> NextInterceptor: index++, 创建新链
NextInterceptor --> Executing: interceptor.intercept()
Executing --> Completed: 返回Response
Executing --> Error: 异常发生
Error --> [*]
Completed --> [*]
note right of NextInterceptor
每次proceed()调用都会:
1. index + 1
2. 创建新的RealInterceptorChain
3. 传递给下一个拦截器
end note
graph TB
A[服务器响应] --> B[ExchangeCodec读取]
B --> C{协议类型}
C -->|HTTP/1.1| D[Http1ExchangeCodec]
C -->|HTTP/2| E[Http2ExchangeCodec]
D --> F[解析状态行]
E --> G[解析HTTP/2帧]
F --> H[解析响应头]
G --> H
H --> I[创建Response.Builder]
I --> J[设置基本信息]
J --> K[设置响应头]
K --> L[创建ResponseBody]
L --> M[构建Response对象]
M --> N[拦截器处理]
N --> O[返回给应用层]
style D fill:#e3f2fd
style E fill:#f3e5f5
style I fill:#e8f5e8
style L fill:#fff3e0
style N fill:#fce4ec
3.6.3 状态行解析流程图
flowchart TD
A[读取状态行] --> B[StatusLine.parse]
B --> C{解析成功?}
C -->|否| D[抛出ProtocolException]
C -->|是| E[提取协议版本]
E --> F[提取状态码]
F --> G[提取状态消息]
G --> H[创建Response.Builder]
H --> I[设置protocol]
I --> J[设置code]
J --> K[设置message]
K --> L{状态码检查}
L -->|100 Continue| M{期望Continue?}
L -->|其他| N[读取响应头]
M -->|是| O[返回null]
M -->|否| P[返回Builder]
N --> Q[返回完整Builder]
style C fill:#fff3e0
style L fill:#e3f2fd
style M fill:#f3e5f5
3.6.4 Headers解析流程
sequenceDiagram
participant Codec as ExchangeCodec
participant Reader as Source/BufferedSource
participant Headers as Headers.Builder
participant Parser as HeaderParser
Codec->>Reader: readHeaderLine()
loop 读取每一行
Reader-->>Codec: 响应头行
alt 空行(响应头结束)
Codec->>Codec: break
else 正常响应头
Codec->>Parser: 解析头部名称和值
Parser-->>Codec: name, value
Codec->>Headers: addLenient(name, value)
else 多行头部(折叠)
Codec->>Parser: 处理折叠行
Parser-->>Codec: 合并后的值
Codec->>Headers: 更新头部值
end
end
Headers-->>Codec: Headers对象
graph TB
A[ResponseBody数据读取] --> B{读取方式选择}
B -->|小数据| C[string方法]
B -->|二进制数据| D[bytes方法]
B -->|流式读取| E[source方法]
B -->|InputStream| F[byteStream方法]
B -->|字符流| G[charStream方法]
C --> H[一次性读取到内存]
D --> I[一次性读取到字节数组]
E --> J[BufferedSource流式读取]
F --> K[InputStream包装]
G --> L[Reader字符流]
H --> M{数据大小}
I --> M
M -->|小于1MB| N[适合]
M -->|大于1MB| O[可能OOM]
J --> P[内存友好]
K --> P
L --> P
style C fill:#ffebee
style D fill:#ffebee
style E fill:#e8f5e8
style F fill:#e8f5e8
style G fill:#e8f5e8
style O fill:#ffcdd2
style P fill:#c8e6c9
3.6.7 Response生命周期
sequenceDiagram
participant App as 应用代码
participant Call as RealCall
participant Chain as InterceptorChain
participant Exchange as Exchange
participant Codec as ExchangeCodec
participant Response as Response
participant Body as ResponseBody
App->>Call: execute() / enqueue()
Call->>Chain: getResponseWithInterceptorChain()
Chain->>Exchange: 拦截器链处理
Exchange->>Codec: readResponseHeaders()
Codec-->>Exchange: Response.Builder
Exchange->>Exchange: openResponseBody()
Exchange->>Body: 创建ResponseBody
Body-->>Exchange: ResponseBody实例
Exchange->>Response: Builder.body().build()
Response-->>Chain: 完整Response
Chain-->>Call: Response
Call-->>App: Response
Note over App: 应用处理Response
App->>Body: string() / bytes() / source()
Body-->>App: 响应数据
App->>Response: close()
Response->>Body: close()
Body->>Codec: 关闭底层连接
3.6.8 响应数据处理
graph TB
A[响应数据处理] --> B{数据大小评估}
B -->|小于64KB| C[直接内存读取]
B -->|64KB-1MB| D[分块读取]
B -->|大于1MB| E[流式处理]
C --> F[string/bytes方法]
D --> G[BufferedSource分块]
E --> H[InputStream/Reader]
F --> I[一次性分配内存]
G --> J[固定大小缓冲区]
H --> K[按需分配]
I --> L{内存充足?}
L -->|是| M[正常处理]
L -->|否| N[OutOfMemoryError]
J --> O[内存可控]
K --> O
style N fill:#ffcdd2
style O fill:#c8e6c9
style M fill:#e8f5e8
3.6.9 Response错误处理
flowchart TD
A[Response处理] --> B{状态码检查}
B -->|2xx| C[成功响应]
B -->|3xx| D[重定向处理]
B -->|4xx| E[客户端错误]
B -->|5xx| F[服务器错误]
C --> G[正常处理ResponseBody]
D --> H[RetryAndFollowUpInterceptor处理]
E --> I[应用层错误处理]
F --> J[可能重试]
G --> K{ResponseBody读取}
K -->|成功| L[返回数据]
K -->|IO异常| M[连接错误处理]
K -->|协议异常| N[协议错误处理]
H --> O[自动重定向]
I --> P[返回错误Response]
J --> Q[重试或失败]
M --> R[关闭连接]
N --> R
R --> S[抛出异常]
style E fill:#fff3e0
style F fill:#ffebee
style M fill:#ffcdd2
style N fill:#ffcdd2
3.6.10 Response缓存机制
sequenceDiagram
participant App as 应用
participant Cache as CacheInterceptor
participant DiskCache as DiskLruCache
participant Network as 网络层
participant Response as Response
App->>Cache: 请求
Cache->>DiskCache: 查找缓存
alt 缓存命中且有效
DiskCache-->>Cache: 缓存Response
Cache->>Response: 创建缓存Response
Response-->>App: 返回缓存数据
else 缓存过期或不存在
Cache->>Network: 网络请求
Network-->>Cache: 网络Response
Cache->>DiskCache: 存储Response
Cache->>Response: 包装为缓存写入Response
Response-->>App: 返回网络数据
Note over Response: 读取时同时写入缓存
end
04.核心流程分析
4.1 请求执行流程
flowchart TD
A[创建OkHttpClient] --> B[构建Request]
B --> C[调用newCall创建Call]
C --> D{同步还是异步?}
D -->|同步| E[call.execute]
D -->|异步| F[call.enqueue]
E --> G[Dispatcher调度]
F --> H[加入异步队列]
H --> I[线程池执行]
I --> G
G --> J[构建拦截器链]
J --> K[依次执行拦截器]
K --> L[发送网络请求]
L --> M[接收响应]
M --> N[拦截器链处理响应]
N --> O[返回Response]
O --> P{异步?}
P -->|是| Q[回调Callback]
P -->|否| R[直接返回]
4.2 连接管理流程
sequenceDiagram
participant Call as RealCall
participant ConnInt as ConnectInterceptor
participant Pool as ConnectionPool
participant Conn as RealConnection
participant Socket as Socket
Call->>ConnInt: intercept()
ConnInt->>Pool: get(address)
alt 连接池中有可用连接
Pool-->>ConnInt: 返回现有连接
else 需要创建新连接
ConnInt->>Conn: create new
Conn->>Socket: connect()
Socket-->>Conn: connected
Conn-->>Pool: put(connection)
Pool-->>ConnInt: 返回新连接
end
ConnInt->>Call: proceed with connection
4.3 缓存处理流程
flowchart TD
A[请求到达缓存拦截器] --> B{缓存是否存在?}
B -->|否| C[继续网络请求]
B -->|是| D{缓存是否有效?}
D -->|有效| E[返回缓存响应]
D -->|需要验证| F[添加条件请求头]
D -->|过期| C
F --> G[发送条件请求]
G --> H{服务器响应}
H -->|304 Not Modified| I[返回缓存内容]
H -->|200 OK| J[更新缓存并返回新内容]
C --> K[网络请求]
K --> L{响应可缓存?}
L -->|是| M[存储到缓存]
L -->|否| N[直接返回响应]
M --> N
05.关键技术特性
5.1 连接池管理
OkHttp使用连接池来复用HTTP连接,提高性能:
java复制代码
public final class ConnectionPool {
private static final Executor executor = new ThreadPoolExecutor(
0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue<>(),
Util.threadFactory("OkHttp ConnectionPool", true)
);
private final RealConnectionPool delegate;
public ConnectionPool() {
this(5, 5, TimeUnit.MINUTES);
}
public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
this.delegate = new RealConnectionPool(taskRunner, maxIdleConnections, keepAliveDuration, timeUnit);
}
}
连接池特性:
默认最大空闲连接数:5个
默认连接保活时间:5分钟
自动清理过期连接
支持HTTP/1.1和HTTP/2连接复用
flowchart TD
A[ConnectionPool创建] --> B[设置最大空闲连接数: 5]
B --> C[设置连接保活时间: 5分钟]
C --> D[创建RealConnectionPool]
D --> E[启动清理线程池]
E --> F[连接使用流程]
F --> G{需要新连接?}
G -->|是| H[创建新连接]
G -->|否| I[复用现有连接]
H --> J[连接加入池中]
I --> K[更新连接使用时间]
J --> L[连接使用完毕]
K --> L
L --> M[连接变为空闲状态]
M --> N[清理线程检查]
N --> O{连接过期?}
O -->|是| P[移除并关闭连接]
O -->|否| Q[保持连接]
P --> R[连接池维护完成]
Q --> R
style A fill:#e3f2fd
style D fill:#f3e5f5
style G fill:#fff3e0
style O fill:#ffebee
5.2 HTTP/2支持
OkHttp完整支持HTTP/2协议:
多路复用:单个连接上并发处理多个请求
服务器推送:服务器主动推送资源
头部压缩:HPACK算法压缩HTTP头部
流量控制:精确控制数据传输速率
5.2.1 HTTP/2连接架构
graph TB
subgraph "HTTP/2多路复用架构"
A[Http2Connection] --> B[Http2Writer]
A --> C[Http2Reader]
A --> D[Settings]
A --> E[流管理器]
E --> F[Http2Stream 1]
E --> G[Http2Stream 2]
E --> H[Http2Stream N]
subgraph "流控制"
I[连接级流控]
J[流级流控]
K[窗口更新]
end
subgraph "帧处理"
L[DATA帧]
M[HEADERS帧]
N[SETTINGS帧]
O[WINDOW_UPDATE帧]
P[PING帧]
end
F --> I
G --> I
H --> I
F --> J
G --> J
H --> J
end
5.3 缓存机制设计
实现完整的HTTP缓存策略:
java复制代码
public final class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = cache != null ? cache.get(chain.request()) : null;
long now = System.currentTimeMillis();
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
Request networkRequest = strategy.networkRequest;
Response cacheResponse = strategy.cacheResponse;
// 缓存策略处理逻辑
if (networkRequest == null && cacheResponse == null) {
return new Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_1_1)
.code(504)
.message("Unsatisfiable Request (only-if-cached)")
.build();
}
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
}
// 继续网络请求...
}
}
5.3.1 缓存架构设计
graph TB
subgraph "OkHttp缓存架构"
A[OkHttpClient] --> B[CacheInterceptor]
B --> C[CacheStrategy]
C --> D[Cache]
D --> E[DiskLruCache]
F[Request] --> G[CacheControl]
H[Response] --> I[Headers]
I --> J[CacheControl]
B --> K[InternalCache]
K --> L[CacheRequest]
K --> M[Response缓存]
subgraph "缓存决策"
C --> N[网络请求]
C --> O[缓存响应]
C --> P[条件请求]
end
subgraph "存储层"
E --> Q[Journal文件]
E --> R[Entry文件]
E --> S[Snapshot]
end
end
flowchart TD
A[接收请求] --> B{检查缓存}
B -->|无缓存| C[发起网络请求]
B -->|有缓存| D{缓存是否新鲜}
D -->|新鲜| E[返回缓存响应]
D -->|过期| F{是否允许过期缓存}
F -->|允许| G{检查max-stale}
F -->|不允许| H{支持条件请求}
G -->|在允许范围内| E
G -->|超出范围| H
H -->|支持| I[发起条件请求]
H -->|不支持| C
I --> J{服务器响应}
J -->|304 Not Modified| K[更新缓存元数据]
J -->|200 OK| L[更新缓存内容]
K --> E
L --> M[返回新响应]
C --> N{响应可缓存}
N -->|可缓存| O[存储到缓存]
N -->|不可缓存| M
O --> M
graph TB
subgraph "DiskLruCache架构"
A[DiskLruCache] --> B[Journal文件]
A --> C[Entry映射]
A --> D[Executor线程池]
B --> E[操作日志]
E --> F[CLEAN记录]
E --> G[DIRTY记录]
E --> H[REMOVE记录]
E --> I[READ记录]
C --> J[Entry对象]
J --> K[文件索引]
J --> L[长度信息]
J --> M[访问时间]
subgraph "文件存储"
N[缓存目录]
N --> O[journal文件]
N --> P[journal.tmp]
N --> Q[journal.bkp]
N --> R[entry.0文件]
N --> S[entry.1文件]
end
end
5.3.5 缓存拦截器思想
CacheInterceptor核心流程
sequenceDiagram
participant I as CacheInterceptor
participant C as Cache
participant D as DiskLruCache
participant F as FileSystem
I->>C: put(response)
C->>C: 计算缓存键
C->>D: edit(key)
D->>D: 创建Editor
D->>F: 创建临时文件
F-->>D: 文件句柄
D-->>C: Editor对象
C->>C: 创建CacheRequest
C-->>I: CacheRequest
Note over I: 写入响应数据
I->>I: cacheWritingResponse()
I->>I: 包装ResponseBody
Note over I: 数据流写入
loop 读取网络响应
I->>I: 读取数据块
I->>C: 写入缓存
I->>I: 写入客户端
end
I->>C: 完成写入
C->>D: editor.commit()
D->>F: 重命名临时文件
D->>D: 更新Journal
D-->>C: 成功
C-->>I: 完成
graph TB
A[OkHttpClient] --> B[SSL/TLS配置]
A --> C[证书验证]
A --> D[主机名校验]
A --> E[连接安全]
B --> F[SSLSocketFactory]
B --> G[X509TrustManager]
B --> H[ConnectionSpec]
B --> I[TlsVersion]
B --> J[CipherSuite]
C --> K[CertificatePinner]
C --> L[CertificateChainCleaner]
C --> M[TrustRootIndex]
D --> N[OkHostnameVerifier]
D --> O[HostnameVerifier]
E --> P[RealConnection]
E --> Q[Handshake]
E --> R[Protocol协商]
F --> S[平台SSL实现]
G --> T[证书信任链]
K --> U[证书固定]
L --> V[证书链清理]
N --> W[主机名匹配]
P --> X[TLS握手]
style A fill:#e3f2fd
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#fce4ec
5.4.2 安全数据流图
sequenceDiagram
participant App as 应用程序
participant Client as OkHttpClient
participant Conn as RealConnection
participant SSL as SSLSocket
participant Server as 服务器
App->>Client: 创建HTTPS请求
Client->>Conn: 建立连接
Conn->>SSL: 创建SSL连接
Note over SSL,Server: TLS握手过程
SSL->>Server: ClientHello
Server->>SSL: ServerHello + Certificate
SSL->>SSL: 证书链验证
SSL->>SSL: 主机名验证
SSL->>SSL: 证书固定检查
alt 验证成功
SSL->>Server: ClientKeyExchange
Server->>SSL: Finished
SSL->>Conn: 安全连接建立
Conn->>Client: 连接就绪
Client->>App: 可以发送请求
else 验证失败
SSL->>Conn: 验证失败
Conn->>Client: 连接异常
Client->>App: 抛出安全异常
end
5.4.3 证书验证机制
OkHttp使用CertificateChainCleaner来清理和验证证书链:
java复制代码
public abstract class CertificateChainCleaner {
public abstract List<Certificate> clean(List<Certificate> chain, String hostname)
throws SSLPeerUnverifiedException;
public static CertificateChainCleaner get(X509TrustManager trustManager) {
return Platform.get().buildCertificateChainCleaner(trustManager);
}
public static CertificateChainCleaner get(X509TrustManager trustManager, TrustRootIndex trustRootIndex) {
return new BasicCertificateChainCleaner(trustRootIndex);
}
}
证书链验证流程
sequenceDiagram
participant Client as OkHttpClient
participant Cleaner as CertificateChainCleaner
participant Trust as TrustManager
participant Root as TrustRootIndex
Client->>Cleaner: clean(certificateChain, hostname)
Cleaner->>Cleaner: 构建完整证书链
loop 对每个证书
Cleaner->>Root: findByIssuerAndSignature(cert)
Root-->>Cleaner: 返回匹配的根证书
end
Cleaner->>Trust: checkServerTrusted(chain, authType)
alt 验证成功
Trust-->>Cleaner: 验证通过
Cleaner-->>Client: 返回清理后的证书链
else 验证失败
Trust-->>Cleaner: 抛出异常
Cleaner-->>Client: 证书验证失败
end
5.4.4 主机名验证
OkHostnameVerifier实现,OkHttp实现了符合RFC 2818标准的主机名验证器
flowchart TD
A[开始主机名验证] --> B{输入是IP地址?}
B -->|是| C[IP地址验证]
B -->|否| D[域名验证]
C --> E[获取证书SAN中的IP地址]
E --> F{IP地址匹配?}
F -->|是| G[验证成功]
F -->|否| H[验证失败]
D --> I[获取证书SAN中的DNS名称]
I --> J[遍历每个DNS名称]
J --> K{是通配符模式?}
K -->|否| L[精确匹配]
K -->|是| M[通配符验证]
L --> N{完全匹配?}
N -->|是| G
N -->|否| O{还有更多DNS名称?}
M --> P[检查通配符规则]
P --> Q{通配符匹配?}
Q -->|是| G
Q -->|否| O
O -->|是| J
O -->|否| H
style G fill:#c8e6c9
style H fill:#ffcdd2
5.4.5 中间人攻击防护
OkHttp通过多层防护机制防止中间人攻击:
graph TB
A[中间人攻击防护] --> B[证书验证]
A --> C[证书固定]
A --> D[主机名验证]
A --> E[HSTS支持]
A --> F[证书透明度]
B --> G[证书链完整性检查]
B --> H[证书有效期验证]
B --> I[证书撤销检查]
C --> J[公钥固定]
C --> K[证书指纹固定]
C --> L[CA固定]
D --> M[SAN验证]
D --> N[通配符规则检查]
D --> O[IP地址验证]
E --> P[强制HTTPS重定向]
E --> Q[HSTS预加载]
F --> R[SCT验证]
F --> S[CT日志检查]
style A fill:#e3f2fd
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#fce4ec
style F fill:#e0f2f1
5.5 SSL/TLS流程
SSL配置层次图
graph TB
A[SSL/TLS配置] --> B[SocketFactory]
A --> C[SSLSocketFactory]
A --> D[X509TrustManager]
A --> E[HostnameVerifier]
A --> F[CertificatePinner]
A --> G[ConnectionSpec]
B --> H[普通Socket创建]
C --> I[SSL Socket创建]
D --> J[证书信任验证]
E --> K[主机名验证]
F --> L[证书固定验证]
G --> M[连接规范配置]
I --> N[TLS握手]
J --> N
K --> N
L --> N
M --> N
N --> O[安全连接建立]
style A fill:#e3f2fd
style N fill:#f3e5f5
style O fill:#c8e6c9
flowchart TD
A[开始TLS协商] --> B{服务器支持TLS 1.3?}
B -->|是| C[使用TLS 1.3]
B -->|否| D{服务器支持TLS 1.2?}
D -->|是| E[使用TLS 1.2]
D -->|否| F{服务器支持TLS 1.1?}
F -->|是| G[使用TLS 1.1]
F -->|否| H{服务器支持TLS 1.0?}
H -->|是| I[使用TLS 1.0]
H -->|否| J[连接失败]
C --> K[建立安全连接]
E --> K
G --> K
I --> K
style C fill:#c8e6c9
style E fill:#dcedc8
style G fill:#f0f4c3
style I fill:#fff9c4
style J fill:#ffcdd2
5.5.3 TLS握手过程
RealConnection负责建立安全的TLS连接:
sequenceDiagram
participant Client as OkHttpClient
participant Conn as RealConnection
participant SSL as SSLSocket
participant Server as 服务器
participant Verifier as HostnameVerifier
participant Pinner as CertificatePinner
Client->>Conn: connectTls()
Conn->>SSL: createSocket()
Conn->>SSL: 配置连接规范
Conn->>SSL: startHandshake()
Note over SSL,Server: TLS握手协商
SSL->>Server: ClientHello
Server->>SSL: ServerHello + Certificate + ServerHelloDone
SSL->>Server: ClientKeyExchange + ChangeCipherSpec + Finished
Server->>SSL: ChangeCipherSpec + Finished
SSL->>Conn: 握手完成
Conn->>Conn: 获取握手信息
Conn->>Verifier: verify(hostname, session)
alt 主机名验证成功
Verifier-->>Conn: true
Conn->>Pinner: check(hostname, certificates)
alt 证书固定验证成功
Pinner-->>Conn: 验证通过
Conn->>Conn: 选择应用层协议
Conn-->>Client: 安全连接建立成功
else 证书固定验证失败
Pinner-->>Conn: SSLPeerUnverifiedException
Conn-->>Client: 连接失败
end
else 主机名验证失败
Verifier-->>Conn: false
Conn-->>Client: SSLPeerUnverifiedException
end
06.性能优化策略
6.1 连接复用
graph LR
A[请求1] --> B[连接池]
C[请求2] --> B
D[请求3] --> B
B --> E[复用连接1]
B --> F[复用连接2]
E --> G[服务器]
F --> G
6.1.1 连接复用架构
graph TB
subgraph "OkHttp连接复用架构"
A[OkHttpClient] --> B[ConnectionPool]
B --> C[RealConnectionPool]
C --> D[RealConnection]
E[Request] --> F[RealCall]
F --> G[ExchangeFinder]
G --> H[RouteSelector]
G --> I[Exchange]
I --> D
subgraph "连接管理"
C --> J[连接清理任务]
C --> K[连接复用逻辑]
C --> L[连接池统计]
end
subgraph "路由选择"
H --> M[Route]
H --> N[Proxy]
H --> O[InetSocketAddress]
end
subgraph "协议支持"
D --> P[HTTP/1.1]
D --> Q[HTTP/2]
D --> R[HTTPS/TLS]
end
end
6.2 请求合并
对于相同的请求,OkHttp会自动合并,避免重复请求。
6.3 压缩传输
自动GZIP压缩响应体
支持Brotli压缩算法
透明的压缩/解压缩处理
6.4 内存管理
使用Okio进行高效的IO操作
智能的缓冲区管理
及时释放不需要的资源
6.4.1 内存管理架构
graph TB
subgraph "OkHttp内存管理架构"
A[内存管理] --> B[对象池化]
A --> C[缓冲区管理]
A --> D[流复用]
B --> E[连接池复用]
B --> F[请求对象复用]
B --> G[响应对象复用]
C --> H[Okio Buffer]
C --> I[Segment池]
C --> J[ByteString缓存]
D --> K[InputStream复用]
D --> L[OutputStream复用]
D --> M[Socket流复用]
subgraph "垃圾回收优化"
N[弱引用使用]
O[及时资源释放]
P[循环引用避免]
end
subgraph "内存监控"
Q[内存使用统计]
R[泄漏检测]
S[性能指标]
end
end
6.4.2 IO操作架构
graph TB
subgraph "OkHttp IO架构"
A[应用层] --> B[OkHttp API]
B --> C[Interceptor Chain]
C --> D[Network Layer]
D --> E[Okio]
E --> F[BufferedSource]
E --> G[BufferedSink]
F --> H[Source]
G --> I[Sink]
H --> J[Socket InputStream]
I --> K[Socket OutputStream]
subgraph "缓冲优化"
L[Segment Buffer]
M[零拷贝操作]
N[批量读写]
end
subgraph "压缩优化"
O[GZip压缩]
P[Deflate压缩]
Q[Brotli压缩]
end
F --> L
G --> L
C --> O
C --> P
end
graph TB
subgraph "OkHttp性能监控架构"
A[EventListener] --> B[连接事件]
A --> C[DNS事件]
A --> D[请求事件]
A --> E[响应事件]
B --> F[连接开始]
B --> G[连接结束]
B --> H[连接获取]
B --> I[连接释放]
C --> J[DNS开始]
C --> K[DNS结束]
D --> L[请求开始]
D --> M[请求头发送]
D --> N[请求体发送]
E --> O[响应头接收]
E --> P[响应体接收]
E --> Q[响应结束]
subgraph "指标收集"
R[连接池统计]
S[请求延迟]
T[吞吐量统计]
U[错误率统计]
end
subgraph "性能分析"
V[热点分析]
W[瓶颈识别]
X[优化建议]
end
end