okhttp介绍

  1. 支持HTTP/2并允许对同一主机的所有请求共享一个套接字(http.1-2 webscoket)
  2. 通过连接池,减少了请求延迟
  3. 默认通过GZip压缩数据
  4. 响应缓存, 避免了重复请求的网络
  5. 请求失败自动重试主机的其他ip, 自动重定向

运行流程

 

分发器dispatcher: 内部维护队列与线程池, 完成请求调配;
拦截器interceptors: 五大默认拦截器完成整个请求过程。

call.enqueue() 后会执行RealCall 里面执行 enqueue()->里面会 new AsyncCall() -> 交给dispatcher。AsyncCall 里面开线程执行 execute()方法 先执行拦截器方法,最后finally 里面调用dispatcher.finished(AsyncCall)

异步请求工作流程 

异步任务2个队列runningAsyncCalls和readyAsyncCalls,同步一个队列

当正在执行的任务未超过最大限制64,同一Host的请求不超过5个,则会添加到正在执行队列,同时提交给线程池。否则先加入等待队列。因此每次执行完一个请求后,都会调用分发器的 finished 方法。在里面正在运行的队列移除当前任务,把等待队列的任务加入。
为什么是64 
1、应为okhttp在写源码的时候,大量参考了浏览器的源码 默认都是64,避免手机和服务器建立过多的线程造成内存溢出 
2、而且这个数是可以改的 

高并发最大吞吐量线程池

 线程创建工厂、是否属于守护线程

拦截器介绍

//自定义拦截器
1、interceptors.addAll(client.interceptors());
//重试拦截器在交出(交给下一个拦截器)之前, 负责判断用户是否取消了请求; 在获得了结果之后, 会根据响3xx应码判断是否需要重定向, 如果满足条件那么就会重启执行所有拦截器(重试与重定向)。
2、interceptors.add(retryAndFollowUpInterceptor);
//桥接拦截器在交出之前, 负责将HTTP协议必备的请求头加入其中(如: Host)并添加一些默认的行为(如: GZIP压缩); 在获得了结果后, 调用保存cookie接口并解析GZIP数据。
3、interceptors.add(new BridgeInterceptor(client.cookieJar()));
//缓存处理拦截器
4、interceptors.add(new CacheInterceptor(client.internalCache()));
//Socket层的握手链接,连接拦截器在交出之前, 负责找到或者新建一个连接, 并获得对应的socket流; 在获得结果后不进行额外的处理。
5、interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
    //网络烂拦截器
    6、interceptors.addAll(client.networkInterceptors());
}
//请求服务器拦截器进行真正的与服务器的通信,client和Server之前的读写操作
7、interceptors.add(new CallServerInterceptor(forWebSocket));//自定义拦截器
interceptors.addAll(client.interceptors());
//重试拦截器在交出(交给下一个拦截器)之前, 负责判断用户是否取消了请求; 在获得了结果之后, 会根据响3xx应码判断是否需要重定向, 如果满足条件那么就会重启执行所有拦截器。
interceptors.add(retryAndFollowUpInterceptor);
//桥接拦截器在交出之前, 负责将HTTP协议必备的请求头加入其中(如: Host)并添加一些默认的行为(如: GZIP压缩); 在获得了结果后, 调用保存cookie接口并解析GZIP数据。
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//缓存处理拦截器
interceptors.add(new CacheInterceptor(client.internalCache()));
//Socket层的握手链接,连接拦截器在交出之前, 负责找到或者新建一个连接, 并获得对应的socket流; 在获得结果后不进行额外的处理。
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
    //网络烂拦截器
    interceptors.addAll(client.networkInterceptors());
}
//请求服务器拦截器进行真正的与服务器的通信,client和Server之前的读写操作
interceptors.add(new CallServerInterceptor(forWebSocket));

1和6 的区别

6可能会被缓存拦截器屏蔽掉 

重定向拦截器讲解

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

重试的前提是出现了 RouteException 或者 IOException 。一但在后续的拦截器执行过程中出现这两个异常,就会通过 recover 方法进行判断是否进行连接重试。
重定向发生在重试的判定之后,如果不满足重试的条件,还需要进一步调用 followUpRequest 根据 Response 的响应码(当然,如果直接请求失败, Response 都不存在就会抛出异常)。 followup 最大发生20次。

 桥接拦截器讲解

 缓存处理拦截器

连接拦截器 

补充一下

HTTP报文格式 

HTTP分块编码

 

Transfer-Encoding: chunked 表示输出的内容长度不能确定,普通的静态页面、图片之类的基本上都用不到这个。配合Content-Encoding: gzip 使用。

Content-Length:先把整个压缩后的数据写到一个很大的字节数组里(ByteArrayOutputStream),然后得到数组大小 。

如果结合Transfer-Encoding: chunked使用,就不必申请一个很大的字节数组了,可以一块一块的输出,占用资源更少。

第一行的3表示下一行需要读几个字节,0表示已经读完。

SSL握手

SA算法交换密钥步骤 
1. 客户端给出协议版本号、一个随机数(Random1),以及客户端支持的加密方法; 
2. 服务端确认使用的加密方法,并给出数字证书、以及随机数(Random2); 
3. 客户端确认数字证书有效,生成一个新的随机数(premaster secret),并使用数字证书中的公钥,利用RSA算法加密这个随机数,发给服务端。 
4. 服务端使用自己的私钥,获取客户端发来的随机数(premaster secret)。 
5. 客户端和服务端根据约定的加密方法,使用前面的三个随机数,生成对话密钥(master secret ),用来加密接下来 的整个对话过程。 整个通话的安全,只取决于第三个随机数(premaster secret)

okhttp自己感觉的不足

里面大部分对象都是new出来的,可以用对象池优化(RealCall,AsyncCall)
等待队列 arraydeque是双端队列 没有用到它的优势

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值