OkHttp3 超时设置

OkHttp3 超时设置,第1张

目录

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 =60  

public 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静态方法的实现

以上~


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11353043.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存