OkHttp是当下Android使用最频繁的网络请求框架。

Google在Android4.4以后,开始将源码中 的HttpURLConnection底层实现 替换为 OKHttp,(即HttpURLConnection底层实现 改为了OKHttp)Retrofifit框架底层同样是使用OKHttp的。
优点:
支持Http1、Http2、Quic以及WebSocket
连接池复用底层TCP(Socket),减少请求延时
无缝的支持GZIP减少数据流量
缓存响应数据减少重复的网络请求
请求失败自动重试主机的其他ip,自动重定向

OKHttp的使用:get请求 和 post请求 ,client.newCall(request)

在使用OkHttp发起一次请求时,使用者最少存在 OkHttpClient 、 Request 与 Call 三个角色。其中
OkHttpClient 和 Request 的创建,可以使用OkHttp为我们提供的 Builder (建造者模式)。
OkHttp在设计时采用的门面模式,将整个系统的复杂性给隐藏起来,将子系统接口通过一个客户端
OkHttpClient统一暴露出来。
OkHttpClient 中全是一些配置,比如代理的配置、ssl证书的配置等。而 Call 本身是一个接口,我们获得的实现 为RealCall.
get请求 和 post请求 ,都执行了client.newCall(request),接下来看newCall()的方法

如果该 RealCall 已经执行过了,再次执行enqueue()方法是不允许的,会抛出异常。异步请求会把一个 AsyncCall 提交给分发器。
AsyncCall 实际上是一个 Runnable 的子类,使用线程启动一个 Runnable 时会执行 run 方法,在 AsyncCall 中被 重定向到 execute 方法:

同时 AsyncCall 也是 RealCall 的普通内部类,这意味着它是持有外部类 RealCall 的引用,可以获得直接调用外 部类的方法。

可以看到无论是同步还是异步请求实际上真正执行请求的工作都在 getResponseWithInterceptorChain() 中。这个 方法就是整个OkHttp的核心:拦截器责任链。但是在介绍责任链之前,我们再来回顾一下线程池的基础知识。

OKHttp的调用 流程

分发器线程池

分发器就是来调配请求任务的,内部会包含一个线程池。当异步请求时,会将请求任务交给线程池
来执行。那分发器中默认的线程池是如何定义的呢?为什么这样定义呢?

在OkHttp的分发器中的线程池定义如上,其实就和 Executors.newCachedThreadPool() 创建的线程一样。首先核 心线程为0,表示线程池不会一直为我们缓存线程,线程池中所有线程都是在60s内没有工作就会被回收。而最大线程数 Integer.MAX_VALUE 与等待队列 SynchronousQueue 的组合能够得到最大的吞吐量,即当需要线程池执行任务时,如果没有空闲线程也不需要等待,会新建线程去执行任务!
等待队列的不同指定了线程池的不同排队机制。一 般来说,等待队列 BlockingQueue 有: ArrayBlockingQueue 、 LinkedBlockingQueue 与 SynchronousQueue 。
假设向线程池提交任务时,核心线程都被占用的情况下:
ArrayBlockingQueue :基于数组的阻塞队列,初始化需要指定固定大小。
当使用此队列时,向线程池提交任务,会首先加入到等待队列中,当等待队列满了之后,再次提交任务,尝试加入队列就会失败,这时就会检查如果当前线程池中的线程数未达到最大线程,则会新建线程执行新提交的任务。所以最终可能出现后提交的任务先执行,而先提交的任务一直在等待。

LinkedBlockingQueue :基于链表实现的阻塞队列,初始化可以指定大小,也可以不指定。
当指定大小后,行为就和 ArrayBlockingQueu 一致。而如果未指定大小,则会使用默认的 Integer.MAX_VALUE 作为队列大小。这时候就会出现线程池的最大线程数参数无用,因为无论如何,向线程池提交任务加入等待队列都会成功。最终意味着所有任务都是在核心线程执行。如果核心线程一直被占,那就一直等待。
SynchronousQueue : 无容量的队列。
(无容量的队列,这样的话,就不会往添加到队列里,只要任务数没有达到最大线程数,就会创建新的线程去执行执行任务)
使用此队列意味着希望获得最大并发量。因为无论如何,向线程池提交任务,往队列提交任务都会失败,因为是没有容量的队列,不缓存队列。而失败后如果没有空闲的非核心线程,就会检查当前线程池中的线程数,如果没有达到最大线程,则会新建线程执行新提交的任务。完全没有任何等待,唯一制约它的就是最大线程数的个数。因此一般配合 Integer.MAX_VALUE 就实现了真正的
无等待。
但是需要注意的时,我们都知道,进程的内存是存在限制的,而每一个线程都需要分配一定的内存。所以线程并不能无限个数。那么当设置最大线程数为 Integer.MAX_VALUE 时,OkHttp同时还有最大请求任务执行个数: 64的限制。这样即解决了这个问题同时也能获得最大吞吐。
拦截器责任链
OkHttp最核心的工作是在 getResponseWithInterceptorChain() 中进行,在进入这个方法分析之前,我们先来了解什么是责任链模式,因为此方法就是利用的责任链模式完成一步步的请求。
责任链模式
在这种模式中,通常每个接收者 都包含 对另一个接收者的 引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下 一个接收者,依此类推。(A包含B, B包含C,C包含D,依次类推)
那整个过程是什么样子的呢?举例如下:

此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

拦截器流程
而OkHttp中的 getResponseWithInterceptorChain() 中经历的流程为

请求会被交给责任链中的一个个拦截器。默认情况下有五大拦截器:
1. RetryAndFollowUpInterceptor
第一个接触到请求,最后接触到响应;负责判断是否需要重新发起整个请求
2. BridgeInterceptor
补全请求,并对响应进行额外处理
3. CacheInterceptor
请求前查询缓存,获得响应并判断是否需要缓存
4. ConnectInterceptor
与服务器完成TCP连接
5. CallServerInterceptor
与服务器通信;封装请求数据与解析响应数据(如:HTTP报文)
拦截器详情
一、重试及重定向拦截器
第一个拦截器: RetryAndFollowUpInterceptor ,主要就是完成两件事情:重试与重定向。
重试
请求阶段发生了 RouteException 或者 IOException会进行判断是否重新发起请求。
RouteException

IOException

两个异常都是根据 recover 方法判断是否能够进行重试,如果返回 true ,则表示允许重试。

所以首先使用者在不禁止重试的前提下,如果出现了某些异常,并且存在更多的路由线路,则会尝试换条线路进行 请求的重试。其中某些异常是在 isRecoverable 中进行判断:

1、协议异常,如果是那么直接判定不能重试;(你的请求或者服务器的响应本身就存在问题,没有按照http协议来 定义数据,再重试也没用)
2、超时异常,可能由于网络波动造成了Socket连接的超时,可以使用不同路线重试。
3、SSL证书异常/SSL验证失败异常,前者是证书验证失败,后者可能就是压根就没证书,或者证书数据不正确, 那还怎么重试?
经过了异常的判定之后,如果仍然允许进行重试,就会再检查当前有没有可用路由路线来进行连接。简单来说,比 如 DNS 对域名解析后可能会返回多个 IP,在一个IP失败后,尝试另一个IP进行重试。

OkHttp原理解析相关推荐

  1. OkHttp原理解析(二)

    前言 上一篇我们学习了OKHttp的请求执行流程,知道了最终请求流程都会交给getResponseWithInterceptorChain方法来执行,接下来我们就详细分析执行getResponseWi ...

  2. OkHttp 原理解析

    一.前言: HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽.OkHttp是一个高效的HTTP客户端,它有以下默认特性: 支持HTTP/2,允许所有同 ...

  3. OkHttp原理解析之面试题分析

    面试中通常是问些问题考察你对OkHttp的原理是否有深入理解. 使用OkHttp发送网络请求并根据请求结果刷新UI有哪几种方式 使用AsyncTask + OkHttp的同步请求 使用OkHttp的异 ...

  4. OkHttp原理解析(一)

    OkHttp 3.10.0版本,最新OkHttp为:4.0.1逻辑与3版本并没有太大变化,但是改为kotlin实现. OkHttp介绍 OkHttp是当下Android使用最频繁的网络请求框架,由Sq ...

  5. OkHttp原理解析(1)

    基于OkHttp 3.10.0版本,最新OkHttp为:4.0.1逻辑与3版本并没有太大变化,但是改为kotlin实现. OkHttp介绍 OkHttp是当下Android使用最频繁的网络请求框架,由 ...

  6. Android:安卓学习笔记之OkHttp原理的简单理解和使用

    Android OkHttp使用原理的简单理解和使用 OkHttp 0.前言 1.请求与响应流程 1.1 请求的封装 1.2 请求的发送 1.3 请求的调度 1.4 请求的处理 2.拦截器 2.1 R ...

  7. OkHttp原理分析总结

    OkHttp原理解析 OkHttp 3.10.0版本,最新OkHttp为:4.0.1逻辑与3版本并没有太大变化,但是改为kotlin实现. OkHttp介绍 OkHttp是当下Android使用最频繁 ...

  8. Android OkHttp完全解析 是时候来了解OkHttp了

    Android OkHttp完全解析 是时候来了解OkHttp了 标签: AndroidOkHttp 2015-08-24 15:36 316254人阅读 评论(306) 收藏 举报  分类: [an ...

  9. OkHttp全解析(一)——基本概念与使用方法

    目录 1.背景 2.基本概念 3.使用方法 4.总结 5.参考 1.背景 kHttp全解析系列文章分为三个部分,包括基本概念与使用方法.原理解析.高级特性的解析.本文为第一部分,基本概念与使用方法,适 ...

最新文章

  1. websphere 启动服务
  2. ue4玻璃材质_UE4-材质
  3. TYAN联合AMD举办线上研讨会,分享最新第三代AMD EPYC服务器产品
  4. php程序设计经典300例,第16-20例
  5. macos 开发环境配置
  6. Java中的java.util包
  7. 【配送路径规划】基于matlab遗传算法求解单配送中心多客户多车辆最短路径规划问题【含Matlab源码 1602期】
  8. 世嘉MD游戏开发【十三】:音乐和音效
  9. 华为od与中软外包哪个更好_华为外包,不是OD,OD也烂,呆了8个月。今天离职再见,…...
  10. 如何下载百度地图离线包并导入OruxMaps
  11. Java高并发累加器Striped64
  12. js下载文件防止白屏
  13. Linux服务.NO7——samba
  14. 2018年互联网公司市值排名
  15. hadoop之常见命令
  16. 以太坊 POA 部署
  17. IDEA自动导包设置
  18. 微信小程序连接百度地图API实现天气查询
  19. 怎么把视频里的音乐提取成音频?
  20. 解决mysql一段时间后不能启动

热门文章

  1. Linux 高并发服务器实战 - 1 Linux系统编程入门
  2. 名帖162 褚遂良 行书《家侄帖》
  3. 阿里云国际版Windows服务器磁盘空间不足该怎么办?
  4. Windows Sysinternals 微软官方免费的极品实用绿色小工具合集,绝对值得你收藏
  5. Linux下启停McAfee防病毒软件
  6. juju创建lxd容器时如何使用本地镜像(by quqi99)
  7. 由Python位运算到原码反码补码
  8. ORA-12518 解决办法
  9. 浮点数的表示 —— 基本格式、规格化、表示范围
  10. Fiddler 抓包工具解析(保存)