如何确定给定`HttpClient`实例的最大并发连接数

时间:2013-09-25 20:48:31

标签: java apache-httpclient-4.x

我有Servlet在启动时构建HttpClient实例。 它与服务请求时使用的协作模块共享此客户端。 我想在其中使用FutureRequestExecutionService API 协作模块可以轻松地同时发送一些请求。 这需要使用HttpClient实例和ExecutorService实例。 tutorial建议将ExecutorService设置为使用与HttpClient的最大并发连接数相同的线程数。

  

futureRequestExecutionService的构造函数接受任何现有的httpClient实例和ExecutorService实例。配置两者时,将最大连接数与您要使用的线程数对齐非常重要。当线程多于连接时,连接可能会因为没有连接而开始超时可用的连接。当连接多于线程时,futureRequestExecutionService将不会使用所有连接。

我认为协作模块应该是为其并发请求创建ExecutorService的模块。在这种情况下的问题是协作模块不一定知道它应该使用多少个线程,因为它不知道HttpClient已配置为允许多少个同时连接。

我知道我可以使用HttpClient的{​​{1}}方法,但从4.3开始,这已被弃用。那么,确定给定getConnectionManager允许的同时连接数的建议方法是什么?我怀疑错误的答案是保存对用于构建HttpClient的{​​{1}}对象的引用,并将其与协作模块一起传递或定义某种全局常量。也许我问的是错误的问题。

也许我应该同时创建ConnectionManagerHttpClientHttpClient个对象,然后只传递 {1}}实例到想要发出HTTP请求的模块 使用共享客户端。我想以符合HttpClient作者意图的方式做到这一点;在这种情况下,我只是不确定究竟是什么。

编辑:为了澄清,ExecutorService实例是使用为其连接管理器设置FutureRequestExecutionService的{​​{1}}创建的。 但是,这与创建FutureRequestExecutionServiceHttpClient的范围不同。 我开始怀疑它们应该一起创建,然后使用HttpClientBuilder实例而不是传递PoolingHttpClientConnectionManager实例。

2 个答案:

答案 0 :(得分:5)

这里的要点是避免太多工作线程最终争用连接太少而导致性能瓶颈的情况。每条路线/总限制的工作线程和连接数量只需要合理:例如,12名工人和10个连接或10名工人和12个连接,但不是12个工人和2个连接。

说了这么多,为了回答你的问题,我不建议紧密耦合PoolingHttpClientConnectionManagerFutureRequestExecutionService布线代码。对我来说,更好的方法应该是拥有一个简单的POJO,甚至是一个表示HTTP服务配置的哈希映射,所有的连接代码都应该依赖于它,而不是直接耦合各种实现类。

沿着这条线的东西

static class MyHttpServiceConfig {
    int workerNum = 10;
};

MyHttpServiceConfig config = new MyHttpServiceConfig();

CloseableHttpClient client = HttpClients.custom()
        .setMaxConnPerRoute(config.workerNum)
        .build();

ExecutorService executor = Executors.newFixedThreadPool(config.workerNum);

FutureRequestExecutionService executionService = new FutureRequestExecutionService(
         client, executor);

答案 1 :(得分:0)

您应该使用PoolingHttpClientConnectionManager来控制可以同时使用的httpClient连接的最大数量。然后,您可以将使用此连接管理器创建的httpClient传递到FutureRequestExecutionService构造函数中。

apache here也提供了一个示例。