OkHttp 3.7源码分析(一)——整体架构
2017-06-19 12:01
459 查看
OkHttp是一个处理网络请求的开源项目,是Android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpUrlConnection和Apache
HttpClient。随着OkHttp的不断成熟,越来越多的android开发者使用OkHttp作为网络框架。
之所以可以赢得如此多开发者的喜爱,主要得益于如下特点:
支持HTTPS/HTTP2/WebSocket(在OkHttp3.7中已经剥离对Spdy的支持,转而大力支持HTTP2)
内部维护任务队列线程池,友好支持并发访问
内部维护连接池,支持多路复用,减少连接创建开销
socket创建支持最佳路由
提供拦截器链(InterceptorChain),实现request与response的分层处理(如透明GZIP压缩,logging等)
为了一探OkHttp是如何具备以下特点的,笔者反复研究OkHttp框架源码,力求通过源码分析向各位解释一二。所以特意准备了几篇博客跟大家一起探讨下OkHttp的方方面面,今天首先从整体架构上分析下OkHttp。
首先来看下OkHttp的简单使用,OkHttp提供了两种调用方式:
同步调用
异步调用
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
首先加锁置标志位,接着使用分配器的executed方法将call加入到同步队列中,然后调用getResponseWithInterceptorChain方法(稍后分析)执行http请求,最后调用finishied方法将call从同步队列中删除
2
3
4
5
6
7
1
2
3
4
5
6
7
同样先置标志位,然后将封装的一个执行体放到异步执行队列中。这里面引入了一个新的类AsyncCall,这个类继承于NamedRunnable,实现了Runnable接口。NamedRunnable可以给当前的线程设置名字,并且用模板方法将线程的执行体放到了execute方法中
除了同步调用和异步调用,OkHttp还提供了一个拦截器的概念。拦截器提供了拦截请求和拦截服务器应答的接口。OkHttp提供了一个拦截器链的概念,通过将一个个拦截器组合成一个拦截器链,可以达到在不同层面做不同拦截操作的效果,有点AOP的意思。具体拦截器的使用可以参考:Okhttp-wiki
之 Interceptors 拦截器
上图是OkHttp的总体架构,大致可以分为以下几层:
Interface——接口层:接受网络访问请求
Protocol——协议层:处理协议逻辑
Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
Cache——缓存层:管理本地缓存
I/O——I/O层:实际数据读写实现
Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
接口层接收用户的网络访问请求(同步请求/异步请求),发起实际的网络访问。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
所以每一个Call就是一个线程,而执行Call的过程就是执行其
Protocol层负责处理协议逻辑,OkHttp支持Http1/Http2/WebSocket协议,并在3.7版本中放弃了对Spdy协议,鼓励开发者使用Http/2。
连接层顾名思义就是负责网络连接。在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求;否则新创建一个网络连接。
连接层是OkHttp的核心部分,这部分当然也会单独拿一篇博客详细讲解,详细内容可参考本专题相关文章。
Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。这部分内容也会单独拿一篇博客进行介绍,详细内容可参考本专题相关文章。
I/O层负责实际的数据读写。OkHttp的另一大有点就是其高效的I/O操作,这归因于其高效的I/O库okio
这部分内容笔者也打算另开一个专题进行介绍。详细内容可以参考本博客相关内容。
拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。在下一篇博客中,笔者将通过介绍一个实际的网络访问请求实例来介绍拦截器的原理。
转自:http://blog.csdn.net/asialiyazhou/article/details/72598320
HttpClient。随着OkHttp的不断成熟,越来越多的android开发者使用OkHttp作为网络框架。
之所以可以赢得如此多开发者的喜爱,主要得益于如下特点:
支持HTTPS/HTTP2/WebSocket(在OkHttp3.7中已经剥离对Spdy的支持,转而大力支持HTTP2)
内部维护任务队列线程池,友好支持并发访问
内部维护连接池,支持多路复用,减少连接创建开销
socket创建支持最佳路由
提供拦截器链(InterceptorChain),实现request与response的分层处理(如透明GZIP压缩,logging等)
为了一探OkHttp是如何具备以下特点的,笔者反复研究OkHttp框架源码,力求通过源码分析向各位解释一二。所以特意准备了几篇博客跟大家一起探讨下OkHttp的方方面面,今天首先从整体架构上分析下OkHttp。
简单使用
首先来看下OkHttp的简单使用,OkHttp提供了两种调用方式:同步调用
异步调用
同步调用
@Override public Response execute() throws IOException { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } try { client.dispatcher().executed(this); Response result = getResponseWithInterceptorChain(false); if (result == null) throw new IOException("Canceled"); return result; } finally { client.dispatcher().finished(this); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
首先加锁置标志位,接着使用分配器的executed方法将call加入到同步队列中,然后调用getResponseWithInterceptorChain方法(稍后分析)执行http请求,最后调用finishied方法将call从同步队列中删除
异步请求
void enqueue(Callback responseCallback, boolean forWebSocket) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket)); }1
2
3
4
5
6
7
1
2
3
4
5
6
7
同样先置标志位,然后将封装的一个执行体放到异步执行队列中。这里面引入了一个新的类AsyncCall,这个类继承于NamedRunnable,实现了Runnable接口。NamedRunnable可以给当前的线程设置名字,并且用模板方法将线程的执行体放到了execute方法中
拦截器
除了同步调用和异步调用,OkHttp还提供了一个拦截器的概念。拦截器提供了拦截请求和拦截服务器应答的接口。OkHttp提供了一个拦截器链的概念,通过将一个个拦截器组合成一个拦截器链,可以达到在不同层面做不同拦截操作的效果,有点AOP的意思。具体拦截器的使用可以参考:Okhttp-wiki之 Interceptors 拦截器
总体架构
上图是OkHttp的总体架构,大致可以分为以下几层:
Interface——接口层:接受网络访问请求
Protocol——协议层:处理协议逻辑
Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
Cache——缓存层:管理本地缓存
I/O——I/O层:实际数据读写实现
Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
Interface——接口层:
接口层接收用户的网络访问请求(同步请求/异步请求),发起实际的网络访问。OkHttpClient是OkHttp框架的客户端,更确切的说是一个用户面板。用户使用OkHttp进行各种设置,发起各种网络请求都是通过
OkHttpClient完成的。每个
OkHttpClient内部都维护了属于自己的任务队列,连接池,Cache,拦截器等,所以在使用OkHttp作为网络框架时应该全局共享一个
OkHttpClient实例。
Call描述一个实际的访问请求,用户的每一个网络请求都是一个
Call实例。
Call本身只是一个接口,定义了
Call的接口方法,实际执行过程中,OkHttp会为每一个请求创建一个
RealCall,每一个
RealCall内部有一个
AsyncCall:
final class AsyncCall extends NamedRunnable { private final Callback responseCallback; AsyncCall(Callback responseCallback) { super("OkHttp %s", redactedUrl()); this.responseCallback = responseCallback; } String host() { return originalRequest.url().host(); } Request request() { return originalRequest; } RealCall get() { return RealCall.this; } @Override protected void execute() { ... } ... }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
AsyncCall继承的
NamedRunnable继承自Runnable接口:
public abstract class NamedRunnable implements Runnable { protected final String name; public NamedRunnable(String format, Object... args) { this.name = Util.format(format, args); } @Override public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(name); try { execute(); } finally { Thread.currentThread().setName(oldName); } } protected abstract void execute(); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
所以每一个Call就是一个线程,而执行Call的过程就是执行其
execute方法的过程。
Dispatcher是OkHttp的任务队列,其内部维护了一个线程池,当有接收到一个
Call时,
Dispatcher负责在线程池中找到空闲的线程并执行其
execute方法。这部分将会单独拿一篇博客进行介绍,详细内容可参考本系列接下来的文章。
Protocol——协议层:处理协议逻辑
Protocol层负责处理协议逻辑,OkHttp支持Http1/Http2/WebSocket协议,并在3.7版本中放弃了对Spdy协议,鼓励开发者使用Http/2。
Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
连接层顾名思义就是负责网络连接。在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求;否则新创建一个网络连接。RealConnection描述一个物理Socket连接,连接池中维护多个RealConnection实例。由于Http/2支持多路复用,一个
RealConnection可以支持多个网络访问请求,所以OkHttp又引入了
StreamAllocation来描述一个实际的网络请求开销(从逻辑上一个
Stream对应一个
Call,但在实际网络请求过程中一个
Call常常涉及到多次请求。如重定向,Authenticate等场景。所以准确地说,一个
Stream对应一次请求,而一个
Call对应一组有逻辑关联的
Stream),一个
RealConnection对应一个或多个
StreamAllocation,所以
StreamAllocation可以看做是
RealConenction的计数器,当
RealConnection的引用计数变为0,且长时间没有被其他请求重新占用就将被释放。
连接层是OkHttp的核心部分,这部分当然也会单独拿一篇博客详细讲解,详细内容可参考本专题相关文章。
Cache——缓存层:管理本地缓存
Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。这部分内容也会单独拿一篇博客进行介绍,详细内容可参考本专题相关文章。
I/O——I/O层:实际数据读写实现
I/O层负责实际的数据读写。OkHttp的另一大有点就是其高效的I/O操作,这归因于其高效的I/O库okio这部分内容笔者也打算另开一个专题进行介绍。详细内容可以参考本博客相关内容。
Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。在下一篇博客中,笔者将通过介绍一个实际的网络访问请求实例来介绍拦截器的原理。转自:http://blog.csdn.net/asialiyazhou/article/details/72598320
相关文章推荐
- OkHttp 3.7源码分析(一)——整体架构
- OkHttp 3.7源码分析(一)——整体架构
- OkHttp 3.7源码分析(一)——整体架构
- 第三方开源库OKHttp-整体架构和源码分析
- jQuery 2.0.3 源码分析core - 整体架构
- jQuery 源码分析core - 整体架构
- 【Spring】Spring源码分析--整体架构
- OkHttp 3.7源码分析(三)——任务队列
- Poseidon(MyBatis)源码分析(1-整体架构分析)
- 【Seajs源码分析】1. 整体架构
- jQuery 2.0.3 源码分析core - 整体架构
- OkHttp 3.7源码分析(四)——缓存策略
- jQuery 2.0.3 源码分析之core(一)整体架构
- OkHttp 3.7源码分析(三) - 任务队列
- Spring源码阅读之准备篇-Spring整体架构分析
- Mongodb 源码分析:整体架构
- OkHttp 3.7源码分析(四)——缓存策略
- Spring 源码分析-整体架构解读
- PostgreSQL整体架构和存储源码的大体分析
- SpringMVC源码剖析(一)SpringMVC整体架构分析和创建