OkHttp深度解析:请求流程、分发器机制、拦截器工作及TCP连接复用
目录
一、OkHttp请求的请求流程是怎样的?
二、OkHttp分发器是怎样工作的?
2.1 请求队列与线程池维护
2.2 异步请求处理
2.3 同步请求处理
2.4 请求执行
2.5 请求完成处理:
2.6 线程池设计
三、OkHttp拦截器是如何工作的?
四、应用拦截器和网络拦截器的区别?
4.1 调用顺序和位置
4.2 功能和用途
五、OkHttp 如何复用TCP 连接的?
5.1 具体过程
5.2 优势
相关推荐
一、OkHttp请求的请求流程是怎样的?
public void sendOkHttp(){
//创建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
//创建Request
Request request = new Request.Builder()
.url("https://shuaici.blog.csdn.net/")
.build();
//创建Call对象client.newCall(request)
Call call = client.newCall(request);
//通过execute()方法获得请求响应的Response对象
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
String result = response.body().string();
//处理UI需要切换到UI线程处理
}
}
});
}
请求流程总结
- 创建OkHttpClient实例:OkHttpClient是OKHttp库的核心类,用于发送HTTP请求和接收HTTP响应。
- 创建Request对象:Request对象封装了HTTP请求的所有信息,包括URL、请求方法(GET、POST等)、请求头部和请求体等。
- 执行请求:
- 通过 OkHttpClient 的 newCall 方法创建 Call 对象。这里的Call是一个接口,实际返回的是它的唯一实现子类RealCall对象。
- 同步请求:通过调用call
.execute()
方法真正发起网络请求,并返回一个Response对象。这种方法会阻塞当前线程,直到请求完成并返回响应。 - 异步请求:通过调用call
.enqueue(callback)
方法真正发起网络请求,并传入一个Callback对象。当请求完成时,OKHttp会自动调用Callback对象的onResponse
或onFailure
方法来处理响应或错误。
- 处理响应:在获取到Response对象后,可以通过调用其方法(如
body().string()
)来获取响应体的内容,并进行相应的处理。
二、OkHttp分发器是怎样工作的?
OkHttp分发器(Dispatcher)的主要作用是调配请求任务,它内部维护了队列和线程池来管理请求的执行。以下是OKHttp分发器的工作机制:
2.1 请求队列与线程池维护
- 分发器内部主要维护了两个队列:
readyAsyncCalls
(等待执行的异步请求队列)和runningAsyncCalls
(正在执行的异步请求队列),以及runningSyncCalls
(正在执行的同步请求队列)。 - 分发器还包含一个线程池
executorService
,用于执行请求任务。
2.2 异步请求处理
- 当发起异步请求时,分发器会检查:
- 同时请求的异步任务数不得大于64(
maxRequests
)和 - 从
readyAsyncCalls队列中取出异步任务其Host,在runningAsyncCalls中不得大于5。
- 则将请求添加到
runningAsyncCalls
队列并立即执行;如果超过了,则将请求加入到readyAsyncCalls
队列中等待。
2.3 同步请求处理
对于同步请求,分发器仅记录请求(放入runningSyncCalls
队列中),因为同步请求不需要线程池,也不存在并发限制,所以分发器仅做记录,后续按照加入队列的顺序同步请求即可。
2.4 请求执行
请求执行是通过分发器将任务分配给拦截器链来完成的。拦截器链负责完成网络请求过程,包括请求重试、缓存处理、建立连接等一系列操作。
2.5 请求完成处理:
请求完成后,分发器会从runningAsyncCalls
或runningSyncCalls
队列中移除对应的请求,并检查是否有等待执行的请求,如果有,则将等待的请求加入到线程池执行
2.6 线程池设计
分发器中的线程池设计为:核心线程数为0,最大线程数为Int.MAX_VALUE
,空闲时间为60秒,工作队列为SynchronousQueue()
。这种设计意味着,当有任务需要执行时,如果线程池中没有可用线程,会直接创建新线程来处理任务。
三、OkHttp拦截器是如何工作的?
OKHttp的拦截器机制是其核心功能之一,它基于责任链模式实现。每个拦截器都可以处理请求或响应,并将请求或响应传递给下一个拦截器。拦截器的工作机制如下:
- 在发起HTTP请求时,OKHttp会依次调用每个拦截器的intercept()方法,将请求传递给下一个拦截器,直到请求被发送到服务器或被拦截器拦截并返回响应为止。
- 在接收到响应后,OKHttp会依次调用每个拦截器的intercept()方法,将响应传递给下一个拦截器,直到响应被处理完毕或被拦截器拦截并返回新的响应为止。
- 拦截器在处理请求和响应时,可以通过Request和Response对象来获取和修改请求和响应的信息。
/**
* 获取响应的拦截器链。
*
* @return Response 对象,包含服务器的响应。
* @throws IOException 如果发生 I/O 错误。
*/
Response getResponseWithInterceptorChain() throws IOException {
// 构建完整的拦截器栈。
List<Interceptor> interceptors = new ArrayList<>();
// 1. 应用拦截器:用户自定义的拦截器,可以在此拦截器中添加自定义逻辑。
interceptors.addAll(client.interceptors());
// 2. 重试重定向拦截器:处理请求重试和重定向逻辑。
interceptors.add(new RetryAndFollowUpInterceptor(client));
// 3. 桥接拦截器:处理请求和响应的转换,例如将请求转换为HTTP/2请求。
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 4. 缓存拦截器:处理缓存逻辑,决定是否从缓存中读取响应或将响应存储到缓存中。
interceptors.add(new CacheInterceptor(client.internalCache()));
// 5. 连接拦截器:处理与服务器建立连接的逻辑,包括DNS解析和TLS握手。
interceptors.add(new ConnectInterceptor(client));
// 如果不是WebSocket请求,添加网络拦截器。
if (!forWebSocket) {
// 6. 网络拦截器:用户自定义的网络层面的拦截器,可以在此拦截器中添加网络层面的自定义逻辑。
interceptors.addAll(client.networkInterceptors());
}
// 7. 服务器调用拦截器:实际向服务器发送请求并接收响应的拦截器,如果是WebSocket请求则特殊处理。
interceptors.add(new CallServerInterceptor(forWebSocket));
// ......
}
四、应用拦截器和网络拦截器的区别?
4.1 调用顺序和位置
- 应用拦截器:先经过应用拦截器,再进入内核,再进入网络拦截器。应用拦截器只关心发起的请求和最终得到的结果,不关心重定向或重试等中间响应。
- 网络拦截器:可以操作重定向或重试的中间响应。如果应用拦截器决定短路并以缓存返回,则网络拦截器就得不到调用。
4.2 功能和用途
- 应用拦截器:常用于日志记录、身份验证、修改请求或响应等操作。它们可以拦截Chain.proceed()或多次调用Chain.proceed()。
- 网络拦截器:更侧重于网络层面的操作,如处理重定向、重试策略等。
五、OkHttp 如何复用TCP 连接的?
OkHttp通过其内置的连接池机制高效地复用了TCP连接。连接池会维护一组已经建立的TCP连接,并在需要发送新的HTTP请求时重用这些连接,而不是每次请求都重新建立一个新的TCP连接。
5.1 具体过程
- 检查连接池:当OkHttp需要发送一个新的HTTP请求时,它首先会检查连接池中是否有可用的TCP连接。这个检查过程是基于目标服务器的IP地址和端口来进行的。
- 复用连接:如果连接池中存在与目标服务器匹配的可用TCP连接,OkHttp就会复用该连接来发送HTTP请求。这意味着,同一个TCP连接上可以发送多个HTTP请求和接收相应的响应,从而减少了每次请求时建立新连接的开销。
- 管理连接生命周期:OkHttp会根据配置的参数(如最大空闲连接数、连接空闲超时等)自动管理连接池中的连接。如果某个连接在一段时间内没有被使用,OkHttp会自动将其关闭,以释放系统资源。
5.2 优势
- 提高性能:通过复用TCP连接,OkHttp显著减少了连接建立和关闭的开销,从而提高了HTTP请求的响应速度和整体性能。
- 减少资源消耗:复用连接可以减少系统资源的消耗,尤其是在高并发的情况下,能够有效减轻服务器的负担。
- 降低网络延迟:已经建立的TCP连接可以直接用于发送新的HTTP请求,无需重新进行TCP三次握手等操作,从而降低了网络延迟。
相关推荐
Android OkHttp使用和源码详解-CSDN博客文章浏览阅读1.5k次,点赞10次,收藏5次。OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App 来说,OkHttp 现在几乎已经占据了所有的网络请求操作,RetroFit + OkHttp 实现网络请求似乎成了一种标配。因此它也是每一个 Android 开发工程师的必备技能,了解其内部实现原理可以更好地进行功能扩展、封装以及优化。_com.squareup.okiohttps://shuaici.blog.csdn.net/article/details/120174041Android OkHttp+Retrofit+Rxjava+Hilt实现网络请求框架-CSDN博客文章浏览阅读3.6k次,点赞37次,收藏47次。本文通过OkHttp+Retrofit+Rxjava+Hilt实现一个网络请求框。 最终代码特别省事。_android response.body().getdata()https://shuaici.blog.csdn.net/article/details/121384534