http连接池参数设置详解

这篇博客探讨了在开发中遇到的NoHttpResponseException问题,深入研究了HTTP连接池的参数设置,包括SpringBean注入配置,如CloseableHttpClient、connManager、keepAliveStrategy、retryHandler和defaultRequestConfig。博客详细解释了connManager的socket配置,connectionKeepAliveStrategy的自定义策略,retryHandler的设定,以及IdleConnectionEvictor的连接清理配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在开发中使用http连接池调用的时候,线上报NoHttpResponseException(具体描述如下),由此展开研究下http连接池参数的具体设置

1:问题描述

java.lang.RuntimeException: org.apache.http.NoHttpResponseException: api.mch.weixin.qq.com:443 failed to respond

java.lang.RuntimeException: org.apache.http.NoHttpResponseException: api.mch.weixin.qq.com:443 failed to respond

2:版本依赖

            <dependency>
               <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.4.1</version>
            </dependency>

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpcore</artifactId>
                <version>4.4.1</version>
            </dependency>

3: SpringBean注入配置

1)httpclient 使用CloseableHttpClient实现类,通过工厂方法模式注入bean。

 <bean id="httpClient" class="org.apache.http.impl.client.CloseableHttpClient"
          factory-bean="httpClientBuilder" factory-method="build"/>

2)分别配置 connManager, keepAliveStrategy, retryHandler, defaultRequestConfig 属性。

   <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder">
        <property name="connectionManager" ref="httpClientConnectionManager"></property>
        <property name="keepAliveStrategy" ref="connectionKeepAliveStrategy"/>
        <property name="retryHandler" ref="retryHandler"/>
        <property name="defaultRequestConfig" ref="requestConfig"/>
    </bean>

  当然该builder还有其他属性需要设置,不过其中有好多都是connectionManager中的属性,源码设置如下,是在connectionManager这个属性没有配置的情况下,才会去利用builder下的属性配置去创建新的connectionManager,比如maxTotal,maxConnPerRoute,假如既配置了connectionManager,又配置了maxTotal等connectionManager的属性,配置的maxTotal是不生效的,只有connectionManager为null,没有配置的时候才生效。

3)connManager配置

    <bean id="httpClientConnectionManager"
          class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager"
          destroy-method="shutdown">
        <!--最大连接数-->
        <property name="maxTotal" value="300"/>
        <!--最大路由连接,每个请求地址的连接数-->
        <property name="defaultMaxPerRoute" value="200"/>
        <!--socketConfig配置-->
        <property name="defaultSocketConfig" ref="socketConfig"/>
        <!--检测不活跃连接的有效性时间-->
        <property name="validateAfterInactivity" value="5000"/>
        <!--连接存活时间-->
        <constructor-arg index="0" value="5"/>
        <constructor-arg index="1" value="SECONDS"/>
    </bean>
  • connManager socket 配置  

  <bean id="socketConfig" class="org.apache.http.config.SocketConfig" factory-bean="socketConfigBuilder" factory-method="build"/>

    <bean id = "socketConfigBuilder" class="org.apache.http.config.SocketConfig.Builder">
          <!--超时时间-->
          <property name="soTimeout" value="2000"/>
    </bean>

4)connectionKeepAliveStrategy
 

 <bean id="connectionKeepAliveStrategy"
          class="com.seven.common.lib.util.HttpClient.BusinessCashierConnectionKeepAliveStrategy"/>

  设置连接空闲可被重用的时间,空闲超过这个时间将不会reuse
  这个KeepAliveStrategy配置可以配置DefaultConnectionKeepAliveStrategy默认的策略

  

默认策略如上,首先看服务端设置的连接超时间是多少,若存在与服务端保持一致,若不存在则设置为-1,一直保持连接。

配置了自己重写的方法如下 ,将最后返回的-1,重置了5s。空闲超过5s将不会被重用

  

5)retryHandler 配置

<bean id="retryHandler" class="org.apache.http.impl.client.DefaultHttpRequestRetryHandler">
    <!--可重试的次数-->
    <constructor-arg index="0" value="3"/>
    <!--设置是否可重试-->
    <constructor-arg index="1" value="true"/>
</bean>

6)defaultRequestConfig

    <bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">
         <!--建立连接超时时间-->
        <property name="connectTimeout" value="2000"/>
        <!--从连接池拿连接超时时间-->
        <property name="connectionRequestTimeout" value="1000"/>
        <!--socket 请求时间-->
        <property name="socketTimeout" value="2000"/>
    </bean>

    <bean id="requestConfig" class="org.apache.http.client.config.RequestConfig"
          factory-bean="requestConfigBuilder" factory-method="build"/>

7)IdleConnectionEvictor 连接擦除配置

 <bean class="org.apache.http.impl.client.IdleConnectionEvictor" init-method="start" destroy-method="shutdown">
        <!--设置连接管理者-->
        <constructor-arg index="0" ref="httpClientConnectionManager"/>
        <!--空闲连接擦除时间-->
        <constructor-arg index="1" value="3"/>
        <constructor-arg index="2" value="SECONDS"/>
    </bean>

 

   

这个注意下init-method这个配置,
当源码看当evictExpiredConnections或者evictIdleConnections为true,擦除空闲连接的线程才会启动,否则不会擦除空闲连接,由于不能直接通过属性注入,所以直接在初始化的时候通过init-method显式打开。

 4:代码配置实现

   RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectRequestTimeout)
                .build();

        ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse httpResponse,
                                             HttpContext httpContext) {

                final HeaderElementIterator it = new BasicHeaderElementIterator(
                        httpResponse.headerIterator(HTTP.CONN_KEEP_ALIVE));
                while (it.hasNext()) {

                    final HeaderElement he = it.nextElement();
                    final String param = he.getName();
                    final String value = he.getValue();
                    if (value != null && param.equalsIgnoreCase("timeout")) {
                        try {
                            logger.info("HeaderElement:{},param:{},value:{}", he, param, value);
                            return Long.parseLong(value) * 1000;
                        } catch (final NumberFormatException ignore) {
                        }
                    }
                }

                if (keepAliveDurationTime != 0) {
                    return keepAliveDurationTime;
                }
                return 5 * 1000l;
            }
        };

        client = HttpClients.custom().setMaxConnPerRoute(maxPerRoute)
                .setMaxConnTotal(maxConnectTotal).setDefaultRequestConfig(requestConfig)
                .setConnectionTimeToLive(connectionTimeToLive, TimeUnit.SECONDS).evictIdleConnections((long) evictIdleConnections, TimeUnit.SECONDS)
                .setKeepAliveStrategy(connectionKeepAliveStrategy).setRetryHandler(new DefaultHttpRequestRetryHandler(3, true))
                .build();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值