Connections - zinclee123/okhttp-wiki GitHub Wiki

使用OkHttp时,虽然只传入了URL,但是OkHttp会使用三种方式连接Web服务,分别是URL、Address和Route

URLs

URL(类似 https://github.com/square/okhttp)是HTTP和互联网的基础。URL不仅可以通用的命名网络上的任何协议,它还指定了如何获取网络资源

URL是抽象的:

  • URLs虽然指定了本次调用是明文的 (http) 还是加密的 (https) ,但是并不指定使用哪种加密算法。也没有指定如何验证对方证书 (HostnameVerifier) ,也没有说明哪些证书是可信任的 (SSLSocketFactory)。
  • URL既不指定使用哪个代理服务器,也不指定如何验证代理服务器

URL也是具体的:每个URL表明了一个指定的路径 (类似 /square/okhttp) 和查询参数 (类似 ?q=sharks&lang=en)。每个Web服务可以对应多个URL。

Addresses

Addresses指定了一个Web服务 (like github.com) 和连接这个服务所需的所有 静态 配置,这些配置如:端口号、HTTPS相关设置以及建议使用的协议(类似 HTTP/2 or SPDY)。

使用同样address的URL有可能使用同样的TCP端口连接。复用连接有诸多好处:降低延迟、提高吞吐量(由于TCP slow start)和降低电耗。OkHttp通过使用 ConnectionPool 自动重用HTTP/1.x类型的连接、多路复用 HTTP/2、SPDY连接。

Address的一部分域是OkHttp从URL中获取的,比如协议、主机名和端口号,剩下的一部分域是通过 OkHttpClient获取。

Routes

Routes提供链接一个Web服务必要的动态信息,比如:指定的IP(通过DNS查询得到)、指定的代理服务器(如果使用了ProxySelector)以及使用什么版本的安全传输层协议(针对HTTPS协议)

一个Address可能会对应多个Route。比如一个Web服务是部署在多个数据中心上,则DNS查询返回中可能就会包含有多个对应的IP地址。

Connections

当你使用OkHttp向一个URL发送请求时,OkHttp内部是这样运作的:

  1. OkHttp使用URL和一个配置好的OkHttpClient对象来创建一个address。这个address指定如何去连接Web服务。
  2. OkHttp会尝试从**连接池(connection pool)**中获取对应这个address的连接。
  3. 如果第2步没有获取到连接,会选择一个route尝试。这步通常会发起一个DNS查询以获取到服务的IP地址。如果有必要的话,也会设置安全传输层协议(TLS)版本和指定代理服务器
  4. 如果是一个新的route,OkHttp会自动选择通过socket、TLS通道(针对使用HTTP proxy的HTTPS)或者TLS创建连接。如果有必要的话也会做TLS握手。
  5. OkHttp发送请求或读取响应

如果连接的过程中出现问题,OkHttp会自动选择其他route尝试重连。这种设计会让OkHttp发现一部分对应该服务已失效的地址。这样的设计让OkHttp在连接池中的某个连接失效或者尝试的TLS版本不支持的时候依然可用。

当接受到响应时,对应的连接会返回到连接池中,这样在发送后续的请求时,可以重用该连接。如果连接在很长一段时间没有被使用时会被自动释放掉。