问题
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 within
the 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.
The constructor for the futureRequestExecutionService takes any existing httpClient instance and an ExecutorService instance. When configuring both, it is important to align the maximum number of connections with the number of threads you are going to use. When there are more threads than connections, the connections may start timing out because there are no available connections. When there are more connections than threads, the futureRequestExecutionService will not use all of them.
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.
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.
Perhaps I should instead create the HttpClient
, ExecutorService
, and FutureRequestExecutionService
objects all at the same time and then pass just the
FutureRequestExecutionService
instance to the modules that want to make HTTP requests
using 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.
EDIT: 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.
回答1:
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.
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.
Something along this line
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);
回答2:
You should use PoolingHttpClientConnectionManager to control the max number of httpClient connection can be used at the same time. And then you can pass in the httpClient you create with this connection manager into the FutureRequestExecutionService constructor.
An example is also provided by apache here.
来源:https://stackoverflow.com/questions/19014919/how-to-determine-the-maximum-number-of-simultaneous-connections-for-a-given-htt