HTTP是一种无连接的事务协议,底层使用的还是TCP,连接池复用的就是TCP连接,目的就是在一个TCP连接上进行多次的HTTP请求从而提高性能。每次HTTP请求结束的时候,HttpClient会判断连接是否可以保持,如果可以则交给连接管理器进行管理以备下次重用,否则直接关闭连接。这里涉及到三个问题:

1、如何判断连接是否可以保持?

要想保持连接,首先客户端需要告诉服务器希望保持长连接,这就是所谓的Keep-Alive模式(又称持久连接,连接重用),HTTP1.0中默认是关闭的,需要在HTTP头加入"Connection: Keep-Alive",才能启用Keep-Alive;HTTP1.1中默认启用Keep-Alive,加入"Connection: close ",才关闭。

但客户端设置了Keep-Alive并不能保证连接就可以保持,这里情况比较复。要想在一个TCP上进行多次的HTTP会话,关键是如何判断一次HTTP会话结束了?非Keep-Alive模式下可以使用EOF(-1)来判断,但Keep-Alive时服务器不会自动断开连接,有两种最常见的方式。

使用Conent-Length

顾名思义,Conent-Length表示实体内容长度,客户端(服务器)可以根据这个值来判断数据是否接收完成。当请求的资源是静态的页面或图片,服务器很容易知道内容的大小,但如果遇到动态的内容,或者文件太大想多次发送怎么办?

使用Transfer-Encoding

当需要一边产生数据,一边发给客户端,服务器就需要使用 Transfer-Encoding: chunked 这样的方式来代替 Content-Length,Chunk编码将数据分成一块一块的发送。它由若干个Chunk串连而成,以一个标明长度为0 的chunk标示结束。每个Chunk分为头部和正文两部分,头部内容指定正文的字符总数(十六进制的数字 )和数量单位(一般不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF) 隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息。

对于如何判断消息实体的长度,实际情况还要复杂的多,可以参考这篇文章:https://zhanjindong.com/2015/05/08/http-keep-alive-header

总结下HttpClient如何判断连接是否保持:

  1. 检查返回response报文头的Transfer-Encoding字段,若该字段值存在且不为chunked,则连接不保持,直接关闭。
  2. 检查返回的response报文头的Content-Length字段,若该字段值为空或者格式不正确(多个长度,值不是整数),则连接不保持,直接关闭。
  3. 检查返回的response报文头的Connection字段(若该字段不存在,则为Proxy-Connection字段)值:
    • 如果这俩字段都不存在,则1.1版本默认为保持, 1.0版本默认为连接不保持,直接关闭。
    • 如果字段存在,若字段值为close 则连接不保持,直接关闭;若字段值为keep-alive则连接标记为保持。

2、 保持多长时间?

保持时间计时开始时间为连接交换至连接池的时间。 保持时长计算规则为:获取response中 Keep-Alive字段中timeout值,若该存在,则保持时间为 timeout值*1000,单位毫秒。若不存在,则连接保持时间设置为-1,表示为无穷。

3、保持过程中如何保证连接没有失效?

很难保证。传统阻塞I/O模型,只有当I/O操做的时候,socket才能响应I/O事件。当TCP连接交给连接管理器后,它可能还处于“保持连接”的状态,但是无法监听socket状态和响应I/O事件。如果这时服务器将连接关闭的话,客户端是没法知道这个状态变化的,从而也无法采取适当的手段来关闭连接。

针对这种情况,HttpClient采取一个策略,通过一个后台的监控线程定时的去检查连接池中连接是否还“新鲜”,如果过期了,或者空闲了一定时间则就将其从连接池里删除掉。ClientConnectionManager提供了 closeExpiredConnections和closeIdleConnections两个方法。

参考文章

HTTP协议头部与Keep-Alive模式详解

又见KeepAlive

HttpClient连接池的连接保持、超时和失效机制的更多相关文章

  1. commons-pool与commons-pool2连接池(Hadoop连接池)

    commons-pool和commons-pool2是用来建立对象池的框架,提供了一些将对象池化必须要实现的接口和一些默认动作.对象池化之后可以通过pool的概念去管理其生命周期,例如对象的创建,使用 ...

  2. JDBC连接池-自定义连接池

    JDBC连接池 java JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  .关闭  ,在实例开发项目中 ,浪费了很大的资源 ,以下是之前连接JDBC的案例 pack ...

  3. 同过增强Connection类[重写了close的方法]实现的从连接池取出连接并放回连接的简单的实现流程

    package tk.dong.connection.util; import java.io.IOException;import java.io.InputStream;import java.i ...

  4. 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 数据库连接不释放测试 连接池 释放连接 关闭连接 有关 redis-py 连接池会导致服务器产生大量 CLOSE_WAIT 的再讨论以及一个解决方案

    import pymysqlfrom redis import Redisimport time h, pt, u, p, db = '192.168.2.210', 3306, 'root', 'n ...

  5. JDBC连接池-C3P0连接

    JDBC连接池-C3P0连接 c3p0连接池的学习英语好的看英文原版      c3p0 - JDBC3 Connection and Statement Pooling 使用c3p0连接池  三种方 ...

  6. java原生程序redis连接(连接池/长连接和短连接)选择问题

    最近遇到的连接问题我准备从重构的几个程序(redis和mysql)长连接和短连接,以及连接池和单连接等问题用几篇博客来总结下. 这个问题的具体发生在java原生程序和redis的交互中.这个问题对我最 ...

  7. psycopg2.pool – Connections pooling / psycopg2.pool – 连接池 / postgresql 连接池

    创建新的PostgreSQL连接可以是一个昂贵的操作.这个模块提供了一些纯Python类直接在客户端应用程序实现简单的连接池.      class psycopg2.pool.AbstractCon ...

  8. 使用DBCP连接池对连接进行管理

    //需要引用的jar包有4个,分别是commons-pool2-2.4.2.jar.commons-dbcp2-2.1.1.jar.mysql-connector-java-5.1.42-bin.ja ...

  9. 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

    1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...

随机推荐

  1. [PHP 作为iOS后台Json格式HTTP通信及文件上传的实现]

    1.数据库连接 configmysql.php <?php $q = mysql_connect("localhost:8889","root",&quo ...

  2. python增删改查(四)

    ###增删改查 names = ["zhangding","wangxu","wudong","cheng"] #增 n ...

  3. cobbler安装、部署、测试

    cobbler功能介绍 官网:http://cobbler.github.io 安装 yum install -y httpd tftp dhcp cobbler cobbler-web pykick ...

  4. js024-最佳实践

    js024-最佳实践 本章内容: 可维护的代码 保证代码性能 部署代码 24.1 可维护性 24.1.1 代码的可维护性 代码可维护性的特征: 特性 说明 可理解性 其他人可以理解它的用途和一般途径 ...

  5. Linux的95个小技巧

    Linux的95个小技巧 by WEB全栈工程师 on 2012 年 03 月 27 日 这里总结了Linux使用中的一些小技巧 1.实现RedHat非正常关机的自动磁盘修复 先登录到服务器,然后在/ ...

  6. MySQL学习笔记——增删改查

    有关数据库的DML操作 -insert into -delete.truncate -update -select -条件查询 -查询排序 -聚合函数 -分组查询 DROP.TRUNCATE.DELE ...

  7. Qt5+VS2012编程

    安装配置 http://www.bogotobogo.com/Qt/Qt5_Visual_Studio_Add_in.php Qt5+GL http://qt-project.org/doc/qt-5 ...

  8. swiper 技巧

    全屏广告高度 ,加上属性. html, body { position: relative; height: 100%; } 停止自行播放 mySwiper.stopAutoplay(); 锁住状态, ...

  9. yourphp点击刷新验证码

    加入css <script type="text/javascript" src="./Public/Js/my.js"></script&g ...

  10. 使用System Sound Services 播放音效(最简单,比较底层),调用AudioServicesPlaySystemSound()

    1.适用范围:一些很小的提示或警告音频. 2.使用限制: 声音长度不能超过30秒 声音文件必须是PCM或IMA4(IMA/ADPCM)格式.(有时候可播放一些特殊的.mp3) 打包成.caf..aif ...