HttpClient连接池的连接保持、超时和失效机制

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如何判断连接是否保持:

检查返回response报文头的Transfer-Encoding字段,若该字段值存在且不为chunked,则连接不保持,直接关闭。
检查返回的response报文头的Content-Length字段,若该字段值为空或者格式不正确(多个长度,值不是整数),则连接不保持,直接关闭。
检查返回的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

引申阅读

浅谈CLOSE_WAIT

又见CLOSE_WAIT

 

时间: 2024-11-03 22:50:07

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

oracle-C# 如何释放连接池的连接

问题描述 C# 如何释放连接池的连接 我们知道.net的数据库连接默认是使用连接池的,这样做有很多好处.但是对于CS结构的应用程序,会消耗很多数据库连接.因此我在oracle数据库端设置了,IDL TIME 空闲时间,即超过一定时间没有操作就关闭连接,但是.net客户端却不能释放连接,所以当Oracle端释放连接后,客户端再执行sql就会报异常.如何做才能释放连接池中的连接呢? 解决方案 只能说你的oracle的数据库的驱动有问题,或者有别的问题..net的连接池当然也是自动管理,不需要释放的.

大牛们,看过来:proxool连接池 获取连接时数组越界

问题描述 如题:用proxool连接池时产生如下错误,不知道是什么原因?按照常理来说这是不可能,获取连接时,连接池的大小是17,怎么会直接指向20,而不是:18呢?org.logicalcobwebs.proxool.hibernatePool-1585946[Thread-165]ERRORorg.logicalcobwebs.proxool.hibernatePool-Problemgettingconnectionjava.lang.IndexOutOfBoundsException:In

c3p0连接池-c3p0 连接不释放 请路过的大神过来看看

问题描述 c3p0 连接不释放 请路过的大神过来看看 配置文件如下 <?xml version="1.0" encoding="UTF-8"?> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://w

连接池用完如何回收到池中,并保证连接池的连接数量

问题描述 哪位可以详细的介绍一下,连接池用完是如何放回池中的,并保证连接池的数量,请详细说一下实现原理,最好有代码,谢谢啦 解决方案 你要自己实现一个连接池?如果不是的话,你也不需要深究其原理,如果你真的想知道的话,那么,你可以去看一下 DBCP 的源码,它是 Tomcat 自带的.其实,它的原理就跟线程池差不多.大概是这个样子的,用一个容器,比如,一个 List,在初始化的时候,就往这个 List 里面存入 10 个 Connection ,然后你需要的话,就从这个 List 中取一个,如果多

HttpClient连接池原理及一次连接时序图

1.       httpClient介绍 HttpClient是一个实现了http协议的开源Java客户端工具库,可以通过程序发送http请求.   1.1.  HttpClient发送请求和接收响应 1.1.1.      代码示例 以Get请求为例,以下代码获得google主页内容并将返回结果打印出来. public final static void main(String[] args) throws Exception {           HttpClient httpclien

一种简单JDBC连接池的实现(二)

3.简单JDBC连接池的实现 根据第二章中原理机制,Snap-ConnectionPool(一种简单快速的连接池工具)按照部分的JDBC规范,实现了连接池所具备的对数据库资源有效管理功能. 3.1体系描述 在JDBC规范中,应用通过驱动接口(Driver Interface)直接方法数据库的资源.为了有效.合理地管理资源,在应用与JDBC Driver之间,增加了连接池: Snap-ConnectionPool.并且通过面向对象的机制,使连接池的大部分操作是透明的.参见下图,Snap-Conne

spring学习笔记(17)数据库配置[1]spring数据连接池详解

数据连接池 在spring中,常使用数据库连接池来完成对数据库的连接配置,类似于线程池的定义,数据库连接池就是维护有一定数量数据库连接的一个缓冲池,一方面,能够即取即用,免去初始化的时间,另一方面,用完的数据连接会归还到连接池中,这样就免去了不必要的连接创建.销毁工作,提升了性能.当然,使用连接池,有一下几点是连接池配置所考虑到的,也属于配置连接池的优点,而这些也会我们后面的实例配置中体现: 1. 如果没有任何一个用户使用连接,那么那么应该维持一定数量的连接,等待用户使用. 2. 如果连接已经满

ODP.NET连接池释放问题

问题描述 大牛们:关于使用odp.net连接操作oracle数据库时连接的释放问题,请教大家,问题如下:连接串:DataSource=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=filesynctest2)(PORT=1521))(CONNECT_DATA=(SID=filesync1)));UserId=xjliu;Password=111111;MaxPoolSize=10;MinPoolSize=1;问题:在默认使用连接池的情况下,程序在查询或操作数

.Net开发中TCP反向代理、Socket 连接池和数据包解析器教程

TCP反向代理 一般的Web反向代理大家很熟悉了,主要是通过在客户端和服务端之间架设一层代理服务器,转发客户端的请求至服务端或数据库,并将结果回复给客户端. 其特点主要有: 1.缓存一些数据库I/O过重.却更新不频繁的数据,或者静态数据,如文件.图片等.2.隔离客户端(公网)和服务端(windows服务.Web服务.文件服务),仅将反向代理服务器的IP.名称.host和端口等暴露给公网.3.基于第2点,其应该是轻量的.可随时重启的,这在服务端自身所在的服务器重启代价较高或不能忍受重启的条件下,极