在HTTP/1.0中keep-alive不是标准协议,客户端必须发送Connection:Keep-Alive来激活keep-alive链接。
HTTP协议是无状态的协议,即每一次请求都是互相独立的。所以它的最初实现是,每个http请求都会打开一个tcp socket链接,当交互完毕后会关闭这个链接。
HTTP协议是全双工的协议,因此创建链接与断开链接是要通过三次握手与四次挥手的。显然在这种设计中,每次发送Http请求都会消耗不少的额外资源,即链接的创建与销毁。
因而,HTTP协议的也进行了发展,经过持久链接的方法来进行socket链接复用。
从图中能够看到:
- 在串行链接中,每次交互都要打开关闭链接
- 在持久链接中,第一次交互会打开链接,交互结束后链接并不关闭,下次交互就省去了创建链接的过程。
持久链接的实现有两种:HTTP/1.0+的keep-alive与HTTP/1.1的持久链接。
HTTP/1.1的链接默认状况下都是持久链接。若是要显式关闭,须要在报文中加上Connection:Close首部。不发送Connection:Close不意味着服务器承诺链接永远保持打开。即在HTTP/1.1中,全部的链接都进行了复用。
HttpClien中使用了链接池来管理持有链接,同一条TCP链路上,链接是能够复用的。HttpClient经过链接池的方式进行链接持久化。
其实“池”技术是一种通用的设计,其设计思想并不复杂:
- 当有链接第一次使用的时候创建链接
- 结束时对应链接不关闭,归还到池中
- 下次同个目的的链接可从池中获取一个可用链接
- 按期清理过时链接 以下:
在HttpClient4.4版本以前,在从链接池中获取重用链接的时候会检查下是否过时,过时则清理。
以后的版本则不一样,会有一个单独的线程来扫描链接池中的链接,发现有离最近一次使用超过设置的时间后,就会清理。默认的超时时间是2秒钟。
总结
- HTTP协议经过持久链接的方式,减轻了早期设计中的过多链接问题
- 持久链接有两种方式:HTTP/1.0+的Keep-Avlive与HTTP/1.1的默认持久链接
- HttpClient经过链接池来管理持久链接,链接池分为两个,一个是总链接池,一个是每一个route对应的链接池
- 默认链接重用策略与HTTP协议约束一致,根据response先判断Connection:Close则关闭,在判断Connection:Keep-Alive则开启,最后版本大于1.0则开启
- 只有在HttpClientBuilder中手动开启了清理过时与空闲链接的开关后,才会清理链接池中的链接
- HttpClient4.4以后的版本经过一个死循环线程清理过时与空闲链接,该线程每次执行都sleep一会,以达到按期执行的效果