关于httpClient 使用的注意事项

本文详细介绍了如何在使用HttpClient时设置连接池大小、连接超时时间以及路由的最大连接数,以优化并发请求性能并避免在高并发场景下的问题。通过实例测试,展示了不同配置对请求响应时间和资源利用的影响。
摘要由CSDN通过智能技术生成

关于httpClient 使用的注意事项

用例
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数-不设置默认20
        connectionManager.setMaxTotal(200);
        // 每个路由最大连接数-不设置默认2
        connectionManager.setDefaultMaxPerRoute(100);
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(
                        RequestConfig.custom()
                                // 连接服务器(握手)的超时时间
                                .setConnectTimeout(3000)
                                // 被请求服务器响应(response)的超时时间
                                .setSocketTimeout(5000)
                                // 从连接池中获取连接的超时时间
                                .setConnectionRequestTimeout(3000)
                                .build()
                ).setConnectionManager(connectionManager)
                .build();
三个连接超时时间
  1. connectionRequestTimeout:从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出ConnectionPoolTimeoutException: Timeout waiting for connection from pool
  2. connectTimeout:连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
  3. socketTimeout:服务器返回数据(response)的时间,超过该时间抛出read timeout
连接池的大小

如果使用默认配置,连接池大小默认为20,即假设被请求接口响应时间为200ms,我们的程序每秒只能完成100个请求响应,剩余的则会陷入等待从连接池获取连接。则在某些高并发的场景中容易出现问题。

路由的大小

DefaultMaxPerRoute 是什么?

可以理解为 IP+端口的一条通路

例如连接池大小(MaxTotal)设置为300,路由连接数设置为200(DefaultMaxPerRoute),对于www.a.comwww.b.com两个路由每个路由的连接数不能超过200来说,两个路由的总连接数不能超过300。

关于setDefaultMaxPerRoute测试
// 服务端测试接口
@RestController
@RequestMapping("/test")
public class TestController {
    @RequestMapping("doTest")
    public Object test(){
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
        return "ok";
    }

    @RequestMapping("doTest1")
    public Object tes1t(){
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
        return "ok";
    }
}


// 客户端测试方法
public class ATest {

    public static Logger log = LoggerFactory.getLogger(ATest.class);
    public static void main(String[] args) {

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数-不设置默认20
        connectionManager.setMaxTotal(2);
        // 每个路由最大连接数-不设置默认2
        connectionManager.setDefaultMaxPerRoute(1);
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(
                        RequestConfig.custom()
                                // 连接服务器(握手)的超时时间
                                .setConnectTimeout(3000)
                                // 被请求服务器响应(response)的超时时间
                                .setSocketTimeout(50000)
                                // 从连接池中获取连接的超时时间
                                .setConnectionRequestTimeout(50000)
                                .build()
                ).setConnectionManager(connectionManager)
                .build();
        new Thread(()->{
            doGet(httpClient,"http://localhost:8080/test/doTest");
        }).start();
        new Thread(()->{
            doGet(httpClient,"http://localhost:8080/test/doTest1");
        }).start();

    }

    private static void doGet(CloseableHttpClient httpClient,String url) {
        HttpGet httpGet = new HttpGet(url);
        try {
            log.info("start");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            log.info("message={}", EntityUtils.toString(response.getEntity()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果

在这里插入图片描述

配置setDefaultMaxPerRoute value为1 ,即同一个ip+端口只能存在一个连接,服务端模拟请求耗时3s,thread-0在请求3s后完成获得响应,并且我们可以看到thread-1实际是在等待thread-0完成请求释放连接后才开始请求,在请求6s后才获得响应

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值