问题描述
我有一个 Servlet
,它在启动时构建一个 HttpClient
实例.它与服务请求时使用的协作模块共享此客户端.我想使用 FutureRequestExecutionService
API 内协作模块可以轻松地并发发送一些请求.这需要使用 HttpClient
实例以及 ExecutorService
实例.教程建议设置ExecutorService
使用与HttpClient
的最大并发连接数相同的线程数.
I have a Servlet
that builds an HttpClient
instance when it starts.It shares this client with a collaborating module used when servicing requests.I would like to use the FutureRequestExecutionService
API withinthe collaborating module to easily send some requests concurrently.This requires using an HttpClient
instance along with an ExecutorService
instance. The tutorial recommends setting the ExecutorService
to use the same number of threads as the HttpClient
's maximum number of concurrent connections.
futureRequestExecutionService 的构造函数采用任何现有的 httpClient 实例和一个 ExecutorService 实例.配置两者时,将最大连接数与您将要使用的线程数保持一致非常重要.当线程数多于连接数时,连接可能会开始超时,因为没有可用连接.当连接数多于线程数时,futureRequestExecutionService 不会全部使用.
我认为协作模块应该是为其并发请求创建 ExecutorService
的模块.这种情况下的问题是协作模块不一定知道它应该使用多少线程,因为它不知道 HttpClient
已配置为允许多少个同时连接.
I thought that the collaborating module should be the one creating the ExecutorService
for its concurrent requests. The problem in that case is that the collaborating module does not necessarily know how many threads it should be using since it doesn't know how many simultaneous connections the HttpClient
has been configured to allow.
我知道我可以使用 HttpClient
的 getConnectionManager
方法,但从 4.3 开始,这已被弃用.那么,确定给定 HttpClient
将允许多少个同时连接的推荐方法是什么?我怀疑错误的答案是保存对用于构建 HttpClient
的 ConnectionManager
对象的引用并将其与协作模块一起传递或定义某种全局常量.也许我问错了问题.
I know I could use HttpClient
's getConnectionManager
method, but as of 4.3 this is deprecated. So then what is the recommended way of ascertaining how many simultaneous connections a given HttpClient
will allow? I suspect that the wrong answer is to save a reference to the ConnectionManager
object used to build the HttpClient
and pass it along with the collaborating module or to define some kind of global constant. Maybe I'm asking the wrong question.
也许我应该同时创建 HttpClient
、ExecutorService
和 FutureRequestExecutionService
对象,然后只传递FutureRequestExecutionService
实例到要发出 HTTP 请求的模块使用共享客户端.我想以一种与 HttpClient 的作者的意图一致的方式来做到这一点;我只是不确定在这种情况下到底是什么.
Perhaps I should instead create the HttpClient
, ExecutorService
, and FutureRequestExecutionService
objects all at the same time and then pass just theFutureRequestExecutionService
instance to the modules that want to make HTTP requestsusing a shared client. I'd like to do this in a manner that is consistent with the intent of the authors of HttpClient; I'm just not sure in this case what that is exactly.
澄清一下,HttpClient
实例是使用 HttpClientBuilder
创建的,该 HttpClientBuilder
为它的连接管理器.但是,这与创建 PoolingHttpClientConnectionManager
和 FutureRequestExecutionService
的范围不同.我开始怀疑它们应该一起创建,然后使用 FutureRequestExecutionService
实例而不是传递 HttpClient
实例.
To clarify, the HttpClient
instance is created using an HttpClientBuilder
that has a PoolingHttpClientConnectionManager
set for its connection manager.However, this does not happen in the same scope as the creation of the PoolingHttpClientConnectionManager
and FutureRequestExecutionService
.I am starting to suspect that they should be created together and then instead of passing the HttpClient
instance around, use the FutureRequestExecutionService
instance.
推荐答案
这里的重点是避免出现太多工作线程最终争用太少连接从而导致性能瓶颈的情况.每个路由的工作线程和连接数/总限制只需要合理:例如,12 个工作线程和 10 个连接或 10 个工作线程和 12 个连接,但不像 12 个工作线程和 2 个连接.
The main point here is to avoid situations when too many worker threads end up contending for too few connections thus causing a performance bottleneck. The number of worker threads and connections per route / total limits just need to be about reasonable: say, 12 workers and 10 connections or 10 workers and 12 connections but not like 12 workers and 2 connections.
说了这么多,要回答您的问题,我不建议将 PoolingHttpClientConnectionManager
和 FutureRequestExecutionService
接线代码紧密耦合.对我来说,更好的方法应该是拥有一个简单的 POJO 或什至是一个表示 HTTP 服务配置的哈希映射,您的所有接线代码都应该依赖它,而不是直接耦合各种实现类.
Having said all that, to answer your question I would not recommend tightly coupling of PoolingHttpClientConnectionManager
and the FutureRequestExecutionService
wiring code. To me a better approach should be having a simple POJO or even a hash map representing HTTP service configuration that all your wiring code should depend upon instead of direct coupling of various implementation classes.
这方面的事情
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);
这篇关于如何确定给定“HttpClient"实例的最大同时连接数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!