1,AsyncTimeout
2-1,耗时段介绍「从上往下」
2-2,4个超时设置「OkHttpClient.Builder」
2-3,耗时 *** 作之间的关联
0,参考
okhttp Timeout 超时设置与用法解释: https://www.jianshu.com/p/7547a5e8524a
1,AsyncTimeout
AsyncTimeout.enter 案例
1,首次创建 Watchdog + AsyncTimeout作为static量,避免重复创建
2,单线程,设置超时,通过pine/pip机制,若超时通过写入流方式唤醒
2-1,耗时段介绍「从上往下」
耗时 *** 作调用位置
DNS解析 「ConnectInterceptor」streamAllocation.newStream
「RouteSelector」address.dns().lookup()
连接时间「ConnectInterceptor」streamAllocation.newStream
「Platform」socket.connect()
写入request 「CallServerInterceptor」httpCodec.writeRequestHeaders
服务器响应 「ConnectInterceptor」streamAllocation.newStream
「RealConnection」socket.connect()
读取response 「CallServerInterceptor」httpCodec.readResponseHeaders
2-2,4个超时设置「OkHttpClient.Builder」
api 简介 生效机制
callTimeout() 整个流程耗费的超时时间 RealCall.execute方法,设置进入
AsyncTimeout + WatchDog实现
connectTimeout()三次握手 + SSL建立耗时 socket.connect(address, connectTimeout)
readTimeout() source读取耗时 source.timeout(readTimeout)
AsyncTimeout + WatchDog实现
rawSocket读取耗时 rawSocket.setSoTimeout(readTimeout)
writeTimeout() sink写入耗时sink.timeout(writeTimeout)
AsyncTimeout + WatchDog实现
重点说一下,callTimeout这个参数,网络上很少人使用。这个就是整个网络流程的超时设置。
2-3,耗时 *** 作之间的关联
route.requiresTunnel() callTimeout = dns + connection + readTimeout + readTimeout + writeTimeout + 其它
无 callTimeout = dns + connectTime + readTimeout + 其它
1,基本耗时:dns + 三次握手耗时 + 服务器响应耗时
2,若有渠道,则增加 source.timeout().(readTimeout) + sink.timeout.(writeTimeout)
我们可以通过OkHttpClient的Builder来设置超时时间
public final static int CONNECT_TIMEOUT =60public final static int READ_TIMEOUT=100
public final static int WRITE_TIMEOUT=60
span style="white-space:pre"> </span>//设置读取超时为100秒,就是为了读取充值的订单
public static OkHttpClient mOkHttpClient =
new OkHttpClient.Builder()
.readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(WRITE_TIMEOUT,TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(CONNECT_TIMEOUT,TimeUnit.SECONDS)//设置连接超时时间
.build()
这个都知道, 一搜一大把, 但是没人讲这三种timeout有什么区别...
源码分析之前先上总结
TCP协议(握手/挥手/发包/丢包重传/滑动窗口/拥塞控制等细节)以及socket属于前置知识, 若不太了解,建议先恶补一下。
以下的源码探究就是罗列记录一下自己的探究过程, 嫌啰嗦可以忽略~
我们知道 okhttp 采用了责任链的设计模式,用一条抽象的 Chain 将一堆 Interceptor 串起来,从发出request 到接收response的路径类似于 node.js 中 koa2 的“洋葱模型”(图1),而 okhttp 的 Interceptor 作用就相当于 koa2 中的 middleware .
“洋葱”的每一层都是一个 Interceptor ,每一层都专注于自己的事情(单一职责),比如日志、mock api,弱网模拟,统一header,APP层缓存、通讯加密等,功能拆分,互不影响,从框架层面来讲也是对AOP思想的具体实践。(AOP可不仅仅是传统意义上的字节码插桩)
okhttp本身已经提供了几个 Interceptor 的默认实现,比如 CacheInterceptor 就是对于http1.1缓存机制的具体实现(cache-controll等) ConnectInterceptor 专门负责创建/复用TCP连接, 里面的 ConnectionPool 就是对 http1.1 中 keep-alive (TCP连接复用)和 pipline 机制(用多条TCP连接实现并发请求)的具体实现。而超时相关的设置也是从这里切入。
上面的 StreamAllocation#newStream 方法就做了两件事,
StreamAllocation#findConnection主要做了两件事,先是从连接池中复用或者创建一个新的连接(RealConnection),然后调用 RealConnection#connect 方法完成 TCP + TLS 握手,其中TCP握手是在
RealConnection#connectSocket(connectTimeout, readTimeout, call, eventListener) 中发起的。
关于 socket.setSoTimeout , 以下是原文档说明的个人翻译及理解
关于 socket.connect(address, connectTimeout)
RealConnection#newCodec() 根据 connection 创建httpCodec(Encodes HTTP requests and decodes HTTP responses.)
当然还有一个地方是在 connectTunnel() 用到, 但是这个前提是走http代理的时候, 这个暂且不详细探究
具体是什么鬼, 看一下source和sink的创建就是知道了
罗列细节之前先总结一下流程:
还是RealConnection的connectSocket方法
Okio.buffer(Source source) 就是 new RealBufferedSource(source)
那么下面主要来看 Okio.source(rawSocket)
跟BuffedSource很相似, 简略描述
同样主要看 Okio.sink(rawSocket) 的实现
sink静态方法的实现
以上~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)