okhttp原理
一、责任链架构原理:
OKHttp 中的责任链模式主要是通过拦截器(Interceptor)来实现的。拦截器是一个实现了 Interceptor 接口的类,该接口定义了一个 intercept 方法,用于处理请求和响应。
OKHttp 中的责任链由一系列拦截器组成,每个拦截器都可以在请求和响应的传递过程中进行处理。当发起一个网络请求时,OKHttp 会按照拦截器的添加顺序,将请求依次传递给每个拦截器进行处理。每个拦截器可以在处理请求和响应时进行自定义的操作,例如添加请求头、处理响应数据、进行重试等。
以下是 OKHttp 中责任链模式的基本原理:
1. 创建拦截器链:在 OKHttp 中,通过 Interceptor.Chain 接口来表示拦截器链。 Interceptor.Chain 接口定义了 proceed 方法,用于将请求传递给下一个拦截器。
2. 添加拦截器:可以通过 OkHttpClient.Builder 的 addInterceptor 和 addNetworkInterceptor 方法添加拦截器。添加的拦截器会按照添加的顺序组成拦截器链。
3. 发起请求:当使用 OkHttpClient 发送请求时,请求会经过拦截器链进行处理。首先,请求会被传递给第一个拦截器,第一个拦截器可以对请求进行处理,并通过调用 chain.proceed 方法将请求传递给下一个拦截器。
4. 拦截器处理:每个拦截器都可以在 intercept 方法中对请求和响应进行处理。在处理完成后,可以选择继续将请求传递给下一个拦截器,或者直接返回响应。
5. 响应返回:当最后一个拦截器处理完成后,会将响应返回给调用方。如果在拦截器链中发生了异常,OKHttp 会根据配置进行相应的处理,例如重试或抛出异常。
通过使用责任链模式,OKHttp 实现了请求和响应的处理流程的解耦和灵活性。可以根据需要添加、删除或修改拦截器,以满足不同的需求。同时,责任链模式也使得 OKHttp 能够方便地扩展和定制功能。
二、双任务队列原理
okhttp双任务队列原理
OkHttp使用两级队列来管理网络请求:
- 同步队列(Dispatcher):这是一个共享队列,所有被添加到同步队列中的任务会在一个线程中顺序执行。
- 异步队列(AsyncCall):每个Runnable都会被封装成AsyncCall添加到此队列中,由线程池执行。
OkHttp的Dispatcher负责管理这两个队列,以及调度他们执行。
以下是OkHttp中的一个简化版本的Dispatcher部分代码:
public final class Dispatcher {
private int maxRequests = 64; // 最大并发请求数
private int maxRequestsPerHost = 5; // 每个主机的最大并发请求数
private Runnable idleCallback;
// 运行队列,存储异步任务
private final Deque runningAsyncCalls = new ArrayDeque<>();
// 等待队列,存储还未运行的异步任务
private final Deque readyAsyncCalls = new ArrayDeque<>();
// 存储正在运行的同步任务
private final Deque runningSyncCalls = new ArrayDeque<>();
}
OkHttp 的双任务队列机制原理主要基于对请求任务的分类和有序管理,以实现高效的网络请求处理。
原理概述:
OkHttp 中的双任务队列通常包括一个“待执行任务队列”和一个“执行中任务队列”。
在“待执行任务队列”中:
- 存放着已经创建但尚未开始执行的请求任务。这些任务可能因为各种条件未满足(如网络未就绪、依赖的前置任务未完成等)而处于等待状态。
在“执行中任务队列”里:
- 则是那些已经开始发送或正在处理中的请求。这包括已经与服务器建立连接、正在传输数据、等待服务器响应等阶段的请求。
工作流程:
当有新的请求创建时:
- 首先会被添加到“待执行任务队列”中。
OkHttp 内部会有一个调度器:
- 不断检查“待执行任务队列”和系统资源(如网络连接、线程可用数等)情况。
- 当条件允许时(如有可用的网络连接和空闲线程),从“待执行任务队列”中取出请求任务,并将其移动到“执行中任务队列”,开始执行网络请求操作。
在请求执行过程中:
- 如果出现异常或需要重试,可能会将请求重新放回“待执行任务队列”。
例如,如果网络连接突然中断,正在进行的请求会被中断并重新放回“待执行任务队列”,等待网络恢复后再次执行。
这种双任务队列机制的好处在于:
- 优化资源利用:可以根据系统当前的资源状况合理安排请求的执行,避免过度消耗资源导致性能下降。
比如,当系统网络繁忙时,不会过度发送请求,而是等待合适的时机。
- 提高并发性能:通过有效地管理不同状态的请求,能够同时处理多个请求,充分利用系统的并发能力。
假设同时有多个请求,OkHttp 可以在处理一个请求的等待时间里,切换去处理其他请求,提高整体效率。
- 增强稳定性和容错性:对于出现问题的请求能够进行合理的重试和重新调度,提高请求的成功率和稳定性。
例如,某个请求由于服务器暂时不可用而失败,它会在合适的时候重新被调度执行。
综上所述,OkHttp 的双任务队列机制通过精细的任务管理和调度,提升了网络请求的性能、稳定性和资源利用效率。
OkHttp 中的双任务队列机制主要用于管理异步请求的执行。它通过使用两个队列,一个等待队列和一个执行队列,来实现任务的调度和复用。
在 OkHttp 中,异步请求的操作元是 Call 对象,其本质是一个 Runnable 线程操作元。当调用 enqueue 方法将 Call 对象添加到任务队列时,会根据一定的条件将其放入等待队列或执行队列。
如果执行队列中的线程数小于最大线程数60, 并且 Call 对象对应的主机数目不超过每个主机的最大请求数5,则将 Call 对象直接放入执行队列,并启动线程执行任务。否则,将 Call 对象放入等待队列。
当一个 Call 对象执行完毕后,会从执行队列中移除,并根据需要调整等待队列中的任务。如果等待队列中有可执行的任务,并且满足条件,则会将其移到执行队列中继续执行。
通过这种双任务队列机制,OkHttp 可以有效地管理异步请求的执行,提高线程的复用率,避免过多的线程创建和销毁,从而提高系统的性能和效率。
三、Socket连接池复用机制原理
连接池的线程池没有主线程,有无限多个子线程,每个线程空闲时,存活60秒后被销毁
OkHttp连接池复用机制原理分析如下:
一、背景介绍
在HTTP通信中,建立和维护TCP连接是一个相对耗时的过程,特别是在高并发的网络环境下。为了减少这种开销,HTTP/1.1引入了keep-alive机制,允许客户端和服务端在请求/响应后保持连接一段时间,以便后续请求可以复用此连接。OkHttp是一个广泛使用的HTTP客户端库,它使用连接池(ConnectionPool)来实现这一机制,进一步提高性能。
二、连接池原理
- 连接池的创建和管理:
-
- OkHttp的连接池是一个存储和管理Socket连接的数据结构。在初始化阶段,可以创建一个连接池对象,并设置最大连接数(maxIdleConnections)、最大空闲连接数以及连接超时等参数。
- 连接池使用线程安全的方式管理连接的获取和释放,确保并发访问的安全性。
- 连接的复用:
-
- 当需要进行网络通信时,OkHttp会首先尝试从连接池中获取一个可用的连接。
- 如果连接池中有空闲连接可用,则直接返回该连接;如果没有空闲连接,则根据需要创建新的连接。
- 在获取到一个连接后,使用它进行网络请求。完成请求后,可以选择将连接返回给连接池,而不是立即关闭该连接。
- 连接的复用策略:
-
- OkHttp的连接池通过维护一个连接队列(Deque)来管理连接的复用。当连接不再使用时,将其标记为可复用状态并放回队列中。
- 在后续请求时,OkHttp会优先从队列中获取可复用的连接,以减少TCP连接的建立和销毁开销。
- 连接的空闲回收:
-
- 为了避免资源浪费,连接池会周期性地检查连接的空闲状态,并进行相应的清理和回收操作。
- 当连接池中的连接空闲时间超过一定阈值(例如,默认的keepAliveDurationNs为5分钟)时,连接池会关闭该连接。
三、OkHttp连接池的实现细节
- 连接池类(ConnectionPool)中包含几个重要变量:
-
- executor线程池:用于执行清理空闲连接的任务。该线程池类似于CachedThreadPool,可以根据需要调整线程数量。
- maxIdleConnections:最大的空闲socket连接数。
- keepAliveDurationNs:socket的keepAlive时间(以纳秒为单位)。
- OkHttp的连接复用实则是依靠ConnectInterceptor连接拦截器实现的。在关键方法上依次会走newStream->findHealthyConnection->findConnection流程,最终获取到一个可用的连接。
- OkHttp的连接池管理策略确保了在高并发场景下,能够有效地复用TCP连接,减少不必要的连接建立和销毁开销,从而提高网络请求的性能和效率。
总之,OkHttp连接池复用机制通过保持和维护一组可用的TCP连接来优化网络通信的性能。在高并发场景下,这种机制能够显著减少TCP连接的建立和销毁开销,提高网络请求的处理速度。