okhttp是目前最流行的网络请求框架,底层封装了socket。httpurlconnection底层也是采用的okhttp(4.4开始)。
okhttpclient采用构建者模式为请求准备一些必要的参数。如添加拦截器addinterceptor(),设置重连接,设置请求连接超时时间,读写超时时间等。
request也是采用构建者模式,构建请求的头信息,方法名,请求地址等。
call封装了请求的具体业务,每个call只能被执行一次,不能重复执行,如果要多次执行需要调用call的clone()克隆一份。
realcall实现了call,真正的请求是交给realcall来处理的。如: 同步请求client.newCall(request).execute(); 异步请求client.newCall(request).enqueue();
请求最终又会交给dispatcher调度器进行调度。 dispatcher调度器维护了三个队列,同步请求队列,异步请求中队列running,异步请求等待队列ready。 当一个新异步请求过来时候,如果running中数量<64并且同一host请求<5,则将请求添加到running队列,否则将新请求添加到ready队列等待。当新request被添加到running队列时,会立马调用execute(call)开启线程池执行,该线程池采用的是核心线程为0,非核心线程为最大int型,闲置超过60秒会回收。然后使用责任链模式调用各种拦截器进行请求处理,最终返回response。当一个请求处理完成后调用dispatcher的finished()方法,将call移出running队列,然后从ready中取call,如果符合要求,会将取出的call添加到running队列,继续执行。
线程池执行原理:当一个请求发来,会检查核心线程是否有,如果有,用核心线程执行该请求,如果核心线程已经没有闲置的了,那么会将请求添加到线程池维护的请求队列,等待执行,当请求队列加满后,有新请求发来,则会检查非核心线程是否达到最大,如果达到最大,则会抛出拒绝的异常,如果非核心线程没达到最大,则创建非核心线程执行新请求。okhttp核心线程为0,非核心线程为int型最大,请求队列为SynchronousQueue容量为0,也就是说只要有请求过来肯定会被马上执行(原因是:dispatcher维护的三个请求队列已经为请求做了充分的安全限制,到线程池后不用担心请求一下子过多这种情况)。
真正执行网络请求的是这个方法 getResponseWithInterceptorChain() 拦截器:采用责任链模式,依次执行以下拦截器 applicationinterceptor:应用拦截器,通过addinterceptor添加,拿到的是原始请求,可以自定义请求头,通用参数,参数加密,网管接入等。 retryandfollowupinterceptor:重试和重定向拦截器,处理错误重试和重定向。 bridgeinterceptor:桥接拦截器,主要工作是为请求添加cookie、添加固定的header,比如Host、Content-Length、Content-Type、User-Agent等等,然后保存响应结果的cookie,如果响应使用gzip压缩过,则还需要进行解压。 cacheinterceptor:缓存拦截器,如果命中缓存,则不发起网络请求。 connectioninterceptor:连接拦截器,内部会维护一个连接池,负责连接复用,创建连接,释放连接,创建连接上的socket流。 networkinterceptor:网络拦截器,用户自定义,通常用于监控网络层的数据传输。 callserverinterceptor:网络请求拦截器,在前置工作准备好后,真正发起网络请求。