OkHttp 原理

一、核心设计思想

OkHttp 的核心架构是 "请求分发 + 拦截器链" 模式,主要基于以下几个设计模式:

设计模式 应用场景
建造者模式 OkHttpClientRequest 的构建
门面模式 OkHttpClient 作为统一入口,隐藏内部复杂性
责任链模式 拦截器链,将请求的发送者和接收者解耦

责任链模式是 OkHttp 的精髓------将网络请求的各个阶段封装到不同的拦截器中,串成一条链,请求沿着链依次传递,每个拦截器各司其职。

二、整体架构流程

#mermaid-svg-LFezjOWfC9vv4PLB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LFezjOWfC9vv4PLB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LFezjOWfC9vv4PLB .error-icon{fill:#552222;}#mermaid-svg-LFezjOWfC9vv4PLB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LFezjOWfC9vv4PLB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LFezjOWfC9vv4PLB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LFezjOWfC9vv4PLB .marker.cross{stroke:#333333;}#mermaid-svg-LFezjOWfC9vv4PLB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LFezjOWfC9vv4PLB p{margin:0;}#mermaid-svg-LFezjOWfC9vv4PLB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LFezjOWfC9vv4PLB .cluster-label text{fill:#333;}#mermaid-svg-LFezjOWfC9vv4PLB .cluster-label span{color:#333;}#mermaid-svg-LFezjOWfC9vv4PLB .cluster-label span p{background-color:transparent;}#mermaid-svg-LFezjOWfC9vv4PLB .label text,#mermaid-svg-LFezjOWfC9vv4PLB span{fill:#333;color:#333;}#mermaid-svg-LFezjOWfC9vv4PLB .node rect,#mermaid-svg-LFezjOWfC9vv4PLB .node circle,#mermaid-svg-LFezjOWfC9vv4PLB .node ellipse,#mermaid-svg-LFezjOWfC9vv4PLB .node polygon,#mermaid-svg-LFezjOWfC9vv4PLB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LFezjOWfC9vv4PLB .rough-node .label text,#mermaid-svg-LFezjOWfC9vv4PLB .node .label text,#mermaid-svg-LFezjOWfC9vv4PLB .image-shape .label,#mermaid-svg-LFezjOWfC9vv4PLB .icon-shape .label{text-anchor:middle;}#mermaid-svg-LFezjOWfC9vv4PLB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LFezjOWfC9vv4PLB .rough-node .label,#mermaid-svg-LFezjOWfC9vv4PLB .node .label,#mermaid-svg-LFezjOWfC9vv4PLB .image-shape .label,#mermaid-svg-LFezjOWfC9vv4PLB .icon-shape .label{text-align:center;}#mermaid-svg-LFezjOWfC9vv4PLB .node.clickable{cursor:pointer;}#mermaid-svg-LFezjOWfC9vv4PLB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LFezjOWfC9vv4PLB .arrowheadPath{fill:#333333;}#mermaid-svg-LFezjOWfC9vv4PLB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LFezjOWfC9vv4PLB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LFezjOWfC9vv4PLB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LFezjOWfC9vv4PLB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LFezjOWfC9vv4PLB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LFezjOWfC9vv4PLB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LFezjOWfC9vv4PLB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LFezjOWfC9vv4PLB .cluster text{fill:#333;}#mermaid-svg-LFezjOWfC9vv4PLB .cluster span{color:#333;}#mermaid-svg-LFezjOWfC9vv4PLB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LFezjOWfC9vv4PLB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LFezjOWfC9vv4PLB rect.text{fill:none;stroke-width:0;}#mermaid-svg-LFezjOWfC9vv4PLB .icon-shape,#mermaid-svg-LFezjOWfC9vv4PLB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LFezjOWfC9vv4PLB .icon-shape p,#mermaid-svg-LFezjOWfC9vv4PLB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LFezjOWfC9vv4PLB .icon-shape .label rect,#mermaid-svg-LFezjOWfC9vv4PLB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LFezjOWfC9vv4PLB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LFezjOWfC9vv4PLB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LFezjOWfC9vv4PLB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 同步
异步


创建 OkHttpClient
构建 Request
client.newCall 创建 RealCall
请求类型
Call.execute
Call.enqueue
Dispatcher.executed

加入 runningSyncCalls
Dispatcher.enqueue

判断并发限制
是否超过

maxRequests=64 或

单Host=5?
加入 runningAsyncCalls

线程池执行
加入 readyAsyncCalls

等待队列
getResponseWithInterceptorChain
拦截器链处理
返回 Response
Dispatcher.finished

移除队列并调度等待任务

2.1 三个核心角色

使用 OkHttp 发起请求时,最少涉及三个角色:

  • OkHttpClient:全局配置容器(代理、SSL、超时、缓存等),建议作为单例
  • Request:封装 URL、Header、Body 等请求信息
  • Call (实际为 RealCall):代表一个已准备好执行的请求,通过 client.newCall(request) 获得

2.2 Dispatcher(分发器)

Dispatcher 负责请求的调度管理,内部包含:

成员 说明 默认值
maxRequests 最大并发请求数 64
maxRequestsPerHost 单域名最大并发数 5
readyAsyncCalls 异步等待队列 ---
runningAsyncCalls 异步执行队列 ---
runningSyncCalls 同步执行队列 ---
executorService 线程池 类似 CachedThreadPool

同步请求 :直接加入 runningSyncCalls 记录,由调用方线程执行。

异步请求 :判断是否超过并发限制------未超过则加入执行队列并提交线程池;超过则先进入等待队列。每次请求完成后,Dispatcher.finished() 会触发等待队列中的任务出队执行。

三、拦截器链(核心)

getResponseWithInterceptorChain() 是 OkHttp 最核心的方法,它按顺序构建拦截器列表:
#mermaid-svg-JheN8NU4X8R9uY5y{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JheN8NU4X8R9uY5y .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JheN8NU4X8R9uY5y .error-icon{fill:#552222;}#mermaid-svg-JheN8NU4X8R9uY5y .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JheN8NU4X8R9uY5y .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JheN8NU4X8R9uY5y .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JheN8NU4X8R9uY5y .marker.cross{stroke:#333333;}#mermaid-svg-JheN8NU4X8R9uY5y svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JheN8NU4X8R9uY5y p{margin:0;}#mermaid-svg-JheN8NU4X8R9uY5y .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JheN8NU4X8R9uY5y .cluster-label text{fill:#333;}#mermaid-svg-JheN8NU4X8R9uY5y .cluster-label span{color:#333;}#mermaid-svg-JheN8NU4X8R9uY5y .cluster-label span p{background-color:transparent;}#mermaid-svg-JheN8NU4X8R9uY5y .label text,#mermaid-svg-JheN8NU4X8R9uY5y span{fill:#333;color:#333;}#mermaid-svg-JheN8NU4X8R9uY5y .node rect,#mermaid-svg-JheN8NU4X8R9uY5y .node circle,#mermaid-svg-JheN8NU4X8R9uY5y .node ellipse,#mermaid-svg-JheN8NU4X8R9uY5y .node polygon,#mermaid-svg-JheN8NU4X8R9uY5y .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JheN8NU4X8R9uY5y .rough-node .label text,#mermaid-svg-JheN8NU4X8R9uY5y .node .label text,#mermaid-svg-JheN8NU4X8R9uY5y .image-shape .label,#mermaid-svg-JheN8NU4X8R9uY5y .icon-shape .label{text-anchor:middle;}#mermaid-svg-JheN8NU4X8R9uY5y .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JheN8NU4X8R9uY5y .rough-node .label,#mermaid-svg-JheN8NU4X8R9uY5y .node .label,#mermaid-svg-JheN8NU4X8R9uY5y .image-shape .label,#mermaid-svg-JheN8NU4X8R9uY5y .icon-shape .label{text-align:center;}#mermaid-svg-JheN8NU4X8R9uY5y .node.clickable{cursor:pointer;}#mermaid-svg-JheN8NU4X8R9uY5y .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JheN8NU4X8R9uY5y .arrowheadPath{fill:#333333;}#mermaid-svg-JheN8NU4X8R9uY5y .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JheN8NU4X8R9uY5y .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JheN8NU4X8R9uY5y .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JheN8NU4X8R9uY5y .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JheN8NU4X8R9uY5y .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JheN8NU4X8R9uY5y .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JheN8NU4X8R9uY5y .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JheN8NU4X8R9uY5y .cluster text{fill:#333;}#mermaid-svg-JheN8NU4X8R9uY5y .cluster span{color:#333;}#mermaid-svg-JheN8NU4X8R9uY5y div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JheN8NU4X8R9uY5y .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JheN8NU4X8R9uY5y rect.text{fill:none;stroke-width:0;}#mermaid-svg-JheN8NU4X8R9uY5y .icon-shape,#mermaid-svg-JheN8NU4X8R9uY5y .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JheN8NU4X8R9uY5y .icon-shape p,#mermaid-svg-JheN8NU4X8R9uY5y .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JheN8NU4X8R9uY5y .icon-shape .label rect,#mermaid-svg-JheN8NU4X8R9uY5y .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JheN8NU4X8R9uY5y .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JheN8NU4X8R9uY5y .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JheN8NU4X8R9uY5y :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用拦截器

client.interceptors
RetryAndFollowUpInterceptor

重试与重定向
BridgeInterceptor

请求/响应适配
CacheInterceptor

缓存处理
ConnectInterceptor

建立连接
网络拦截器

client.networkInterceptors
CallServerInterceptor

读写数据

3.1 各拦截器职责

拦截器 职责
应用拦截器(自定义) 用户添加,最先执行,可处理公共参数、Header 等
RetryAndFollowUpInterceptor 连接失败自动重试、处理重定向
BridgeInterceptor 补全请求头(Content-Type、Content-Length、Host、Cookie 等),解压 GZIP 响应
CacheInterceptor 根据 HTTP 缓存策略,判断是否使用缓存
ConnectInterceptor 从连接池获取或新建 TCP 连接
网络拦截器(自定义) 用户添加,在连接建立后、数据读写前执行,常用于监控网络层数据
CallServerInterceptor 最后一个拦截器,通过 HttpCodec 向服务器写出请求数据、读取响应数据

3.2 责任链传递机制

每个拦截器的 intercept(Chain chain) 方法分为三部分:

  1. 预处理:处理当前拦截器自身的逻辑
  2. 传递 :调用 chain.proceed(request) 将请求交给下一个拦截器
  3. 后处理:下一个拦截器返回 Response 后的后续处理

四、连接池与连接复用

TCP 连接需要三次握手,开销较大。OkHttp 通过 连接池(ConnectionPool) 复用 TCP 连接来减少延迟。
#mermaid-svg-ZXWPaCjdiO4SQZrB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZXWPaCjdiO4SQZrB .error-icon{fill:#552222;}#mermaid-svg-ZXWPaCjdiO4SQZrB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZXWPaCjdiO4SQZrB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .marker.cross{stroke:#333333;}#mermaid-svg-ZXWPaCjdiO4SQZrB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZXWPaCjdiO4SQZrB p{margin:0;}#mermaid-svg-ZXWPaCjdiO4SQZrB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster-label text{fill:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster-label span{color:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster-label span p{background-color:transparent;}#mermaid-svg-ZXWPaCjdiO4SQZrB .label text,#mermaid-svg-ZXWPaCjdiO4SQZrB span{fill:#333;color:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .node rect,#mermaid-svg-ZXWPaCjdiO4SQZrB .node circle,#mermaid-svg-ZXWPaCjdiO4SQZrB .node ellipse,#mermaid-svg-ZXWPaCjdiO4SQZrB .node polygon,#mermaid-svg-ZXWPaCjdiO4SQZrB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .rough-node .label text,#mermaid-svg-ZXWPaCjdiO4SQZrB .node .label text,#mermaid-svg-ZXWPaCjdiO4SQZrB .image-shape .label,#mermaid-svg-ZXWPaCjdiO4SQZrB .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZXWPaCjdiO4SQZrB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .rough-node .label,#mermaid-svg-ZXWPaCjdiO4SQZrB .node .label,#mermaid-svg-ZXWPaCjdiO4SQZrB .image-shape .label,#mermaid-svg-ZXWPaCjdiO4SQZrB .icon-shape .label{text-align:center;}#mermaid-svg-ZXWPaCjdiO4SQZrB .node.clickable{cursor:pointer;}#mermaid-svg-ZXWPaCjdiO4SQZrB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .arrowheadPath{fill:#333333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZXWPaCjdiO4SQZrB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZXWPaCjdiO4SQZrB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZXWPaCjdiO4SQZrB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster text{fill:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB .cluster span{color:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZXWPaCjdiO4SQZrB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZXWPaCjdiO4SQZrB rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZXWPaCjdiO4SQZrB .icon-shape,#mermaid-svg-ZXWPaCjdiO4SQZrB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZXWPaCjdiO4SQZrB .icon-shape p,#mermaid-svg-ZXWPaCjdiO4SQZrB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZXWPaCjdiO4SQZrB .icon-shape .label rect,#mermaid-svg-ZXWPaCjdiO4SQZrB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZXWPaCjdiO4SQZrB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZXWPaCjdiO4SQZrB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZXWPaCjdiO4SQZrB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有

请求到达 ConnectInterceptor
根据 Address

查找可用连接
连接池中

是否有可用连接?
复用已有连接
创建新连接

TCP三次握手
存入连接池
执行请求
请求完成
连接归还连接池

不立即关闭
连接池清理线程

清理闲置连接

4.1 连接复用的关键点

  • Address :由 URL 的 Scheme、Host、Port 以及 OkHttpClient 的配置(如 HTTPS 设置)共同决定。相同 Address 的请求可共享同一个 Socket 连接。
  • 连接池策略:请求完成后连接不立即关闭,而是放回连接池供后续复用。
  • 清理机制:连接池有后台清理线程,定期关闭闲置连接。

4.2 应用拦截器 vs 网络拦截器

面试常见问题:

应用拦截器 网络拦截器
执行时机 最早执行,在重试和重定向之前 ConnectInterceptor 之后、CallServerInterceptor 之前
调用次数 只调用一次 可能调用多次(每次重试/重定向都会调用)
适用场景 公共参数注入、日志打印 网络监控、流量统计

五、面试回答要点总结

回答"OkHttp 原理"时,可以按以下逻辑串联:

  1. 一句话概括 :OkHttp 基于责任链模式 ,通过拦截器链 处理请求的各个阶段,配合Dispatcher 调度请求,连接池复用 TCP 连接。

  2. 流程简述OkHttpClient + RequestRealCallexecute()/enqueue()Dispatcher 调度 → getResponseWithInterceptorChain() → 拦截器链依次处理 → 返回 Response

  3. 亮点展开(挑 1-2 个深入):

    • 拦截器链:7 个拦截器的职责和顺序
    • 连接池Address 决定连接复用,减少三次握手开销
    • Dispatcher:并发控制(64/5)和线程池调度
相关推荐
殷忆枫3 小时前
BOA服务器下实现视频回放功能(CGI+软链接方案)
服务器·okhttp·音视频
消失的旧时光-19432 天前
第十篇:Ktor Custom Client Plugin:从 OkHttp Interceptor 真正理解请求与响应生命周期
okhttp·plugin·ktor·kmp
mmsx3 天前
基于 Android 的校园信息管理系统源码
android·java·okhttp
Full Stack Developme10 天前
跨站请求伪造 (CSRF) 是什么 设计及工作原理
前端·okhttp·csrf
weixin_4407841112 天前
【OkHttp实现原理】
android·java·okhttp
AZaLEan__24 天前
原生XMLHttpRequest + axios + fetch
okhttp
Android-Flutter24 天前
OkHttp 总结
android·okhttp·kotlin
zhangjin11201 个月前
Okhttp系列:POST请求
okhttp