1、OkHttp请求整体流程是怎么样?
Request-》OkHttpClient-》RealCall
同步 -》 在调用线程 执行五大拦截器
异步 -》 使用分发器将任务在线程池执行 五大拦截器
2、分发器是如何工作的?
同步-》记录同步任务:RealCall
异步-》首先将任务加入ready队列等待执行 -》是否需要将ready中的任务放入running 执行
同时请求的异步任务数不得大于64个
从ready中取出来的异步任务,与其相同的HOST,不得大于5个
若已经存在5个相同HOST的任务在执行,则继续从ready中检查下一个等待任务
3、拦截器是如何工作的?
责任链设计模式 将请求者 与 执行者 解耦
让请求者 只需要将请求发给责任链即可,无需关系请求过程与细节。
重试重定向、桥接、缓存、连接、请求服务
4、应用拦截器与网络拦截器的区别?
OkHttp中拦截器有:自定义应用拦截器、重试重定向、桥接、缓存、连接、自定义网络拦截器、请求服务。自定义应用拦截器与自定义网络拦截器的区别主要是顺序的区别,由于以上拦截器采用责任链设计模式组合执行,因此顺序不同,带来的影响是:应用拦截器不需要关心是否重定向或者失败重连(只会执行一次);同时它也能决定是否执行其他拦截器。而网络拦截器则可以操作重定向与重试并且可能不会执行(直接在缓存中获得结果),同时它也可以观察到真正的Request以及相关的连接信息(经过其他拦截器处理完毕后)。
5、OkHttp如何复用TCP连接
连接池 容器缓存所有的有效连接对象
清理 垃圾连接
超过了5分钟没用过的连接会被清理
超过了5个闲置连接后,从最久闲置的连接开始执行清理 (LRU),直到闲置连接少于5个。
6、OkHttp缓存机制
OkHttp基于Http协议实现了缓存,但是默认是关闭状态,需要在配置OkHttpClient时候使用:OkHttpClient.Builder().cache(Cache(文件,大小)) .build() 开启。
OkHttp只会缓存GET请求的响应,在RFC7231中GET,HEAD和某些情况下的POST都是可缓存的,但是绝大多数的实现里只支持GET和HEAD的缓存,这是因为post做的一般是修改和删除的工作,所以必须与服务端交互,所以不能使用缓存。
而Http的缓存又分为强缓存与协商缓存。
强缓存
强缓存的意思是:浏览器并不会将请求发送给服务器。与强缓存相关的响应头有两个:
-
expires,它的值为一个绝对时间,如果发送请求的时间在expires之前,那么本地缓存有效,能够直接使用缓存。
-
cache-control:max-age=number,资源第一次的请求时间和该值相加,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。另外此响应头还能设置为:
- no-cache:不使用本地缓存。
- no-store:不允许被缓存
- public:可以被任何用户缓存,包括终端用户和CDN等中间代理服务器。
- private:只能被终端用户缓存,不允许CDN等中间代理服务器缓存。
- immutable:(响应)资源不会改变
协商缓存
协商缓存的意思是:浏览器会将请求发送至服务器。服务端可能响应304(不包含响应体数据)表示缓存可用,可能正常响应,如200同时携带响应体。为了让服务端判断是否可用缓存,在请求时,需要携带标识:If-Modified-Since或者If-None-Match 。
其中If-Modified-Since需要和响应的Last-Modified 配合使用,而If-None-Match 则与Etag 配合。
Last-Modified/ If-Modified-Since
在缓存的响应中响应头包含:Last-Modified
,表示服务端告知的对应请求的资源在服务器上的最后修改时间。再次发起请求,需要在请求头中携带:If-Modified-Since
。其值就是响应中的Last-Modified
的值。意思就是告诉服务端我的缓存,在服务端什么时候修改后拿到的。服务端判断这个时间后是否修改过资源,未修改则返回3-04,否则正常返回响应数据。
Etag/If-None-Match
这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变。在请求时携带If-None-Match
,其值是缓存的响应头中的Etag
,服务端获取到请求头中的If-None-Match
会重新计算此次请求资源的标识,如果一致则返回304。