OkHttp框架源码解析——整体架构

前言

OkHttp是一个处理网络请求的开源项目,是android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpUrlConnection和Apache HttpClient。OkHttp有如下特点:

  • 支持HTTP / HTTP2 / WebSocket
  • 内部维护任务队列线程池,友好支持并发访问
  • 内部维护连接池,支持多路复用,减少连接创建开销
  • socket创建支持最佳路由
  • 提供拦截器,实现request与response的分层处理(如透明GZIP压缩,logging等)

整体架构

OkHttp的整体架构如下:

  • Interface:接口层,接收网络访问的请求
  • Protocol:协议层,处理协议逻辑
  • Connection:连接层,管理网络连接,发送新的请求,接收服务器访问
  • Cache:缓存层,管理本地缓存
  • I / O :I / O 层,实际数据读写实现
  • InterceptChain:拦截器层,拦截网络访问,插入拦截逻辑

接下来详细分析一下这几个层次。

Interface接口层

接口层接收用户的网络访问请求(同步请求 / 异步请求),发起实际的网络访问。

OkHttpClient是OkHttp框架的客户端,更确切的说是一个用户面板。用户使用OkHttp进行各种设置,发起各种网络请求都是通过OkHttpClient完成的。每个OkHttpClient内部维护了属于自己的任务队列,连接池,Cache,拦截器等,所以在使用OkHttp作为网络框架时应该全局共享一个OkHttpClient实例。

Call描述一个实际的访问请求,用户的每一个网络请求都是一个Call实例。Call实例本身是一个接口,定义了Call的接口方法,实际执行过程中,OkHttp会为每一个请求创建一个RealCall,每一个RealCall内部有一个AsyncCall。AsyncCall继承的NamedRunnable继承子Runnable接口,所以每一个Call就是一个线程,而执行Call的过程就是执行其execute方法的过程。

Dispatcher是OkHttp的任务队列,其内部维护了一个线程池,当有接收到一个Call时,Dispatcher负责在线程池中找到空闲的线程并执行其execute方法。

Protocol协议层

Protocol层负责处理协议逻辑,OkHttp支持HTTP1 / HTTP2 / WebSocket 协议,并在3.7版本中放弃对Spdy协议,鼓励开发者使用HTTP 2。

Connection连接层

连接层主要就是负责网络连接,是OkHttp的核心部分。在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求,否则新创建一个网络连接。

RealConnection描述一个物理Socket连接,连接池中维护多个RealConnection实例。由于Http2 支持多路复用,一个RealConnection可以支持多个网络访问请求,所以OkHttp又引入了StreamAllocation来描述一个实际的网络请求开销(从逻辑上一个Stream对应一个Call,但在实际网络请求过程中一个Call常常涉及到多次请求。如重定向,Authenticate等场景。所以准确的说,一个Stream对应一次请求,而一个Call对应一组有逻辑关联的Stream),一个RealConnection对应一个或多个StreamAllocation,所以StreamAllocation可以看做是RealConnection的计数器,当RealConnection的引用计数变为0,且长时间没有被其他请求占用就将被释放。

Cache缓存层

Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。

I / O 层

I / O 层负责实际的数据读写。OkHttp的另一大特点就是其高效的I / O操作,这归因于其高效的I / O库okio。

Interceptor拦截器层

拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。

小结

最后附上各个层次的总揽图。