HttpClient 4.3连接池参数配置及源码解读

    目前所在公司使用HttpClient 4.3.3版本发送Rest请求,调用接口。最近出现了调用查询接口服务慢的生产问题,在排查整个调用链可能存在的问题时(从客户端发起Http请求->ESB->服务端处理请求,查询数据并返回),发现原本的HttpClient连接池中的一些参数配置可能存在问题,如defaultMaxPerRoute、一些timeout时间的设置等,虽不能确定是由于此连接池导致接口查询慢,但确实存在可优化的地方,故花时间做一些研究。本文主要涉及HttpClient连接池、请求的参数配置,使用及源码解读。

 

    以下是本文的目录大纲:

    一、HttpClient连接池、请求参数含义

    二、执行原理及源码解读

        1、创建HttpClient,执行request

        2、连接池管理

            2.1、连接池结构

            2.2、分配连接 & 建立连接

            2.3、回收连接 & 保持连接

            2.4、instream.close()、response.close()、httpclient.close()的区别

            2.5、过期和空闲连接清理

    三、如何设置合理的参数

 

一、HttpClient连接池、请求参数含义

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.CodingErrorAction;
import javax.net.ssl.SSLException;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.MessageConstraints;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;

public class HttpClientParamTest {
	public static void main(String[] args) {
		/**
		 * 创建连接管理器,并设置相关参数
		 */
		//连接管理器,使用无惨构造
		PoolingHttpClientConnectionManager connManager 
		                            = new PoolingHttpClientConnectionManager();
		
		/**
		 * 连接数相关设置
		 */
		//最大连接数
		connManager.setMaxTotal(200); 
		//默认的每个路由的最大连接数
		connManager.setDefaultMaxPerRoute(100); 
		//设置到某个路由的最大连接数,会覆盖defaultMaxPerRoute
		connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 150); 
		
		/**
		 * socket配置(默认配置 和 某个host的配置)
		 */
		SocketConfig socketConfig = SocketConfig.custom()
				.setTcpNoDelay(true)     //是否立即发送数据,设置为true会关闭Socket缓冲,默认为false
				.setSoReuseAddress(true) //是否可以在一个进程关闭Socket后,即使它还没有释放端口,其它进程还可以立即重用端口
				.setSoTimeout(500)       //接收数据的等待超时时间,单位ms
				.setSoLinger(60)         //关闭Socket时,要么发送完所有数据,要么等待60s后,就关闭连接,此时socket.close()是阻塞的
	            .setSoKeepAlive(true)    //开启监视TCP连接是否有效
	            .build();
		connManager.setDefaultSocketConfig(socketConfig);
		connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);
		
		/**
		 * HTTP connection相关配置(默认配置 和 某个host的配置)
		 * 一般不修改HTTP connection相关配置,故不设置
		 */
		//消息约束
		MessageConstraints messageConstraints = MessageConstraints.custom()
	            .setMaxHeaderCount(200)
	            .setMaxLineLength(2000)
	            .build();
		//Http connection相关配置
		ConnectionConfig connectionConfig = ConnectionConfig.custom()
	            .setMalformedInputAction(CodingErrorAction.IGNORE)
	            .setUnmappableInputAction(CodingErrorAction.IGNORE)
	            .setCharset(Consts.UTF_8)
	            .setMessageConstraints(messageConstraints)
	            .build();
		//一般不修改HTTP connection相关配置,故不设置
		//connManager.setDefaultConnectionConfig(connectionConfig);
        //connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);
		
        /**
         * request请求相关配置
         */
		RequestConfig defaultRequestConfig = RequestConfig.custom()
				.setConnectTimeout(2 * 1000)         //连接超时时间
                .setSocketTimeout(2 * 1000)          //读超时时间(等待数据超时时间)
                .setConnectionRequestTimeout(500)    //从池中获取连接超时时间
                .setStaleConnectionCheckEnabled(true)//检查是否为陈旧的连接,默认为true,类似testOnBorrow
                .build();
		
		/**
		 * 重试处理
		 * 默认是重试3次
		 */
		//禁用重试(参数:retryCount、requestSentRetryEnabled)
		HttpRequestRetryHandler requestRetryHandler = new DefaultHttpRequestRetryHandler(0, false);
		//自定义重试策略
		HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {

		    public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
		    	//Do not retry if over max retry count
		        if (executionCount >= 3) {
		            return false;
		        }
		        //Timeout
		        if (exception instanceof InterruptedIOException) {
		            return false;
		        }
		        //Unknown host
		        if (exception instanceof UnknownHostException) {
		            return false;
		        }
		        //Connection refused
		        if (exception instanceof ConnectTimeoutException) {
		            return false;
		        }
		        //SSL handshake exception
		        if (exception instanceof SSLException) {
		           
<think>好的,我现在要处理用户的问题:如何在Spring Boot中使用RestTemplate集成HttpClient5连接池并进行相关配置。用户希望得到教程式的指导,所以我需要逐步分解步骤,确保配置方法正确,并且语法无误。 首先,我需要回忆一下Spring Boot中RestTemplate和HttpClient5的结合使用。记得RestTemplate默认使用的是简单的HTTP客户端,但可以通过自定义来替换成HttpClient5,尤其是使用连接池来提高性能。 第一步应该是添加依赖。用户需要引入HttpClient5的库,可能还需要Apache的HttpClient5依赖项。正确的Maven依赖应该是org.apache.httpcomponents.client5的httpclient5和httpclient5-fluent。同时,可能还需要连接池的依赖,比如httpclient5的pool2模块?或者是否HttpClient5本身已经包含了连接池的实现?需要确认这一点,避免遗漏依赖。 接下来,配置连接池的参数。需要创建一个连接管理器,比如PoolingAsyncClientConnectionManager,并设置最大连接数、每个路由的最大连接数等参数。然后,使用这个连接管理器构建HttpClient实例。这里可能需要调整一些参数,比如超时时间和保持活跃策略。 然后,将HttpClient5与RestTemplate结合。需要创建HttpComponentsClientHttpRequestFactory的实例,并将HttpClient传递进去,再将这个工厂设置到RestTemplate中。需要注意的是,HttpClient5的包名可能和旧版本不同,比如从org.apache.httpcomponents升级到client5包下,所以代码中的类引用是否正确很重要,避免出现类找不到的错误。 配置参数方面,用户可能需要调整连接池的最大连接数、路由最大连接数、超时时间、空闲连接验证等。这部分需要详细说明每个参数的作用和推荐值,比如默认的最大连接数设为多少合适,或者根据应用需求调整。 此外,可能需要处理SSL配置,特别是如果用户需要访问HTTPS端点的话。这部分是否需要包括在内?用户的问题中没有明确提到SSL,但可能需要简要提及或作为可选步骤。 测试配置是否生效也是关键的一步。可以通过日志查看连接池的使用情况,或者编写单元测试来发送多个请求,观察连接是否复用。这部分可以建议用户如何验证配置是否正确应用。 然后,我需要检查是否有站内引用需要插入。用户提供的引用是关于Spring Boot Actuator的,可能与当前问题无关,但可能需要确认是否有其他相关引用。根据用户给出的引用,可能不需要在此处使用,但需要确保回答中的引用正确。 最后,生成相关问题。可能需要包括如何监控连接池状态、常见配置错误、性能调优等,帮助用户进一步了解相关主题。 在整理步骤时,需要确保使用正确的中文术语,代码示例无误,并且配置参数解释清晰。同时,注意LaTeX格式的应用,如变量或配置项需要用$...$包裹,例如$maxTotal$等。独立公式可能用不上,但如果有数学表达式则需要用$$...$$。 可能遇到的错误点包括依赖版本不兼容,类名或包名错误,配置参数名称不正确等。需要提醒用户注意版本匹配,比如HttpClient5需要Spring Boot的哪个版本支持,或者是否需要排除旧版的HttpClient依赖。 总结步骤:添加依赖→配置连接池管理器→创建HttpClient实例→创建RestTemplate Bean→配置参数说明→测试验证。每个步骤都需要详细说明,确保用户能一步步操作。</think>### 在Spring Boot中集成RestTemplate与HttpClient5连接池 以下是分步配置教程: --- #### 1. 添加依赖 在`pom.xml`中引入HttpClient5和连接池依赖: ```xml <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5-fluent</artifactId> <version>5.2.1</version> </dependency> ``` --- #### 2. 配置连接池管理器 创建连接池配置类: ```java import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; @Configuration public class HttpClientConfig { @Bean public PoolingHttpClientConnectionManager poolingConnectionManager() { PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(); manager.setMaxTotal(200); // 全局最大连接数 manager.setDefaultMaxPerRoute(50); // 每个路由最大连接数 return manager; } } ``` --- #### 3. 创建HttpClient实例 配置超时和连接管理器: ```java import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.classic.HttpClient; @Bean public HttpClient httpClient(PoolingHttpClientConnectionManager manager) { return HttpClients.custom() .setConnectionManager(manager) .evictExpiredConnections() // 自动清理过期连接 .setConnectionTimeToLive(30, TimeUnit.SECONDS) // 连接存活时间 .build(); } ``` --- #### 4. 创建RestTemplate Bean 将HttpClient绑定到RestTemplate: ```java import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @Bean public RestTemplate restTemplate(HttpClient httpClient) { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); factory.setConnectTimeout(5000); // 连接超时5秒 factory.setReadTimeout(10000); // 读取超时10秒 return new RestTemplate(factory); } ``` --- #### 5. 关键配置参数说明 | 参数 | 作用 | 推荐值 | |-----------------------|--------------------------|--------------| | `setMaxTotal` | 全局最大连接数 | 根据负载调整 | | `setDefaultMaxPerRoute`| 单路由最大连接数 | 50-100 | | `setConnectTimeout` | 建立TCP连接超时时间 | 5000ms | | `setConnectionTimeToLive` | 连接空闲存活时间 | 30s | --- #### 6. 验证配置 通过日志查看连接池状态: ```properties # application.properties logging.level.org.apache.http=DEBUG ``` 调用测试接口观察日志中的`leased`和`available`连接数变化。 --- ###
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值