Spring AsyncRestTemplate connection pool and thread pool settings - spring

I want to use AsyncRestTemplate for making a REST call in my service. According to Spring documentation, this class has 5 constructors( refer http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/AsyncRestTemplate.html)
AsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory)-Using this AsyncClientHttpRequestFactory argument I will be able to configure the connection pool.
AsyncRestTemplate(AsyncListenableTaskExecutor taskExecutor)-Using this I will be able to configure the thread pool for the async operation.
I want to know if there is a way I could configure both connection pool and thread pool in AsyncRestTemplate.
Thank you very much in adance.

You can set task executor in SimpleClientHttpRequestFactory also:
ThreadPoolTaskScheduler taskExecutor = new ThreadPoolTaskScheduler();
taskExecutor.setPoolSize(10);
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setTaskExecutor(taskExecutor);
new AsyncRestTemplate(simpleClientHttpRequestFactory);

Related

Monitor connection pool of PoolingHttpClientConnectionManager

I'd like to monitor the connection pool of a Apache httpComponents PoolingHttpClientConnectionManager but cannot find a way to access it.
We create our HttpClient using the following builder:
HttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(maxConnections)
.setMaxConnPerRoute(maxConnectionsPerRoute)
.build();
This creates an instance of an InternalHttpClient, which holds an instance of a PoolingHttpClientConnectionManager, which holds an instance of a CPool.
CPool would give us access to T getRoutes() and PoolStats getStats(T) — which looks promising to me. But I can't really find out how to get access to this CPool.
HttpClient.getConnectionManager() is deprecated. InternalHttpClient.getConnectionManager() is not deprecated, but returns a custom connection manager, which only exposes some of the methods of the real connection manager instance behind it.
So, how to get access to these stats? These would be very helpful for us.
Use ConnPoolControl implemented by PoolingHttpClientConnectionManager
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
ConnPoolControl<HttpRoute> connPoolControl = cm;
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(cm)
.build();

RestTemplate HttpClient connectionRequestTimeout

In order to configure RestTemplate I use the following configuration:
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(HttpClients.createDefault());
httpRequestFactory.setConnectTimeout(connectionTimeoutMs);
httpRequestFactory.setConnectionRequestTimeout(readTimeoutMs);
httpRequestFactory.setReadTimeout(readTimeoutMs);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
I understand the purpose of connection and read timeouts. But I don't understand the purpose of connection request timeout. It also not clear from Javadoc what does it mean. Could you please explain it ?
As the docs say :
Set the timeout in milliseconds used when requesting a connection from
the connection manager using the underlying HttpClient.
It means the maximum amount of time you will allow to the connection manager to give you an available connection from its pool (so it has nothing to do with the RESTservice itself you'll reach).
To define a custom connection manager, you can use this :
CloseableHttpClient httpClientBuilder = HttpClientBuilder.create().setConnectionManager(...).build();
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder);

Springs RestTemplate default connection pool

Just wondering if RestTemplate out of the box uses connection pooling or does it simply establish a new connection each time ?
Yes, Spring RestTemplateBuilder uses Apache HttpClient for pooling (usage).
RestTemplateBuilder creates HttpComponentsClientHttpRequestFactory and uses HttpClientBuilder.
HttpClientBuilder, by default, sets pool size per route (host) to 5 and total pool size to 10 (source):
s = System.getProperty("http.maxConnections", "5");
int max = Integer.parseInt(s);
poolingmgr.setDefaultMaxPerRoute(max);
poolingmgr.setMaxTotal(2 * max);
To check connection pool logging set logging level as follows:
org.apache.http.impl.conn.PoolingHttpClientConnectionManager=TRACE
I believe RestTemplate doesn’t use a connection pool to send requests, it uses a SimpleClientHttpRequestFactory that wraps a standard JDK’s HttpURLConnection opening and closing the connection.
Indeed you can configure RestTemplate to use a pooled implementation such as HttpComponentsClientHttpRequestFactory but most-likely you might also need to configure some settings to prevent requests from timing out.
I have blogged about this issue at Troubleshooting Spring's RestTemplate Requests Timeout
By default RestTemplate creates new Httpconnection every time and closes the connection once done.
If you need to have a connection pooling under rest template then you may use different implementation of the ClientHttpRequestFactory that pools the connections.
new RestTemplate(new HttpComponentsClientHttpRequestFactory())
You can create a Bean for RestTemplate and config there :
#Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectionRequestTimeout(5000) // timeout to get connection from pool
.setSocketTimeout(5000) // standard connection timeout
.setConnectTimeout(5000) // standard connection timeout
.build();
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
And there are a lot config you can do. Refer to https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html
EDIT
If you want to use micrometer metrics you should also use a RestTemplateBuilder for constructing the RestTemplate.
In case of using Spring Boot configured with Apache HttpClient (having org.apache.httpcomponents:httpclient library in dependencies)
There is a default connection pool configured by PoolingHttpClientConnectionManager
Default concurrent settings for connections (you can find more about default settings here https://hc.apache.org/httpcomponents-client-4.5.x/current/tutorial/html/connmgmt.html):
PoolingHttpClientConnectionManager maintains a maximum limit of connections on a per route basis and in total. Per default this implementation will create no more than 2 concurrent connections per given route and no more 20 connections in total. For many real-world applications these limits may prove too constraining, especially if they use HTTP as a transport protocol for their services.
We can use okhttpclient underneath spring's rest template to use connection pooling. A detailed blog on this below
https://www.bytesville.com/changing-httpclient-in-spring-resttemplate/

Java concurrent safe worker pool queue

I am writing Spring (Java 8) web application and per each request(separate thread) my application make a few tasks, which should be completed as quickly as possible to return result to client in browser, so I'd like to find worker pool library, which can be accessed from different threads in safe way.
I have read about Execution pool, Rabbit MQ, but I couldn't find information about the feature of accessing the tasks queue from different threads.
I will really appreciate if somebody can give me advice how to do it in Java.
Here you can use asynchronous method call supported by Spring via #Async annotation.
The #Async annotated method will be executed in new thread and the result will be available in Future object (void return is also supported). Do note that the method call is non-blocking which will help return the response quickly without waiting for every task to complete. However if required the main thread can be made to wait for all task i.e. Future to complete via Future.get() which is blocking.
To configure the asynchronous support, annotate the configuration class with #EnableAsync and provide below method definition as described here.
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.initialize();
return executor;
}

How to integrate asyncHttpClient with commonj workmanager?

We have a use case that a single request from end user will trigger 1 or more http requests to other remote systems. All responses from remote systems will be aggregated into one single response to end user. We had this by using commonj workmanager in websphere.
Now, we want to use asyncHttpClient in order to have lesser threads to service multiple concurrent http calls.
So my question is:
How to integrate asyncHttpClient with commonj workmanager? We have to use commonj as thread pool as it's the only way to have managed threads in wehsphere.
Please advise.
All you need to do is create a new ExecutorService that leverages the work manager as shown below. More details...
Lookup the WorkManager and construct the WASThreadFactory
InitialContext ctx = new InitialContext();
WorkManager wm = (WorkManager)ctx.lookup("java:comp/env/wm/default");
ThreadFactory tf = new WASThreadFactory(wm);
Create a ThreadPoolExecutor using a bounded buffer
BlockingQueue q = new ArrayBlockingQueue(50);
ExecutorService myOwnThreadPool= = new ThreadPoolExecutor(
1, 10, 5000, TimeUnit.MILLISECONDS, q, tf);
According to their documentation, you can specify the ExecutorService to be used as below
Builder builder = new AsyncHttpClientConfig.Builder();
builder.setExecutorService(myOwnThreadPool);
AsyncHttpClient client = new AsyncHttpClient(builder.build());
NOTE: Didn't verify for compilation. I've however used this in my earlier project.

Resources