Springs RestTemplate default connection pool
Asked Answered
H

6

45

Just wondering if RestTemplate out of the box uses connection pooling or does it simply establish a new connection each time ?

Hoelscher answered 25/5, 2017 at 19:57 Comment(0)
B
37

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

Brobdingnagian answered 25/5, 2017 at 20:46 Comment(5)
Do I need to create my resttemplate beans as prototype if I use pool?Indiaindiaman
@EugeneMakarenko No. How many instances of RestTemplate are you planning to instantiate?Brobdingnagian
I need 10 RestTemplates for each service for data transfer and 5 RestTemplates for authentication service. Do I need to inject these beans into my services as singletons or to create using the prototype scope per each request if I am going to use the connection pool from your article? I don't understand how the pool will return used RestTemplate back.Indiaindiaman
@EugeneMakarenko, why would you need 10 instances? RestTemplate is thread-safe. You can use the same RestTemplate instance to send requests to multiple services. Just configure it properly so that one slow service won't hijack the whole pool.Brobdingnagian
thank you! I was wrong. I have another question. I use two types of RestTemplates. The first is configured for authorization and the second uses for data receiving. Can I use one connection pool for them?Indiaindiaman
E
40

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
Ensemble answered 31/12, 2018 at 8:49 Comment(6)
RestTemplateBuilder? This answer may be correct but not seeing RestTemplateBuilder in spring dependencies. If you do new RestTemplate(), you're getting a SimpleClientHttpRequestFactory not HttpComponentsClientHttpRequestFactory. Using new RestTemplate(HttpComponentsClientHttpRequestFactory); seems the way to go.Tusche
This answer is correct. Don't be confused if you find different defaults (e.g. 2/ 20 or 5/25) when browsing the Internet. Those apply if you instantiate PoolingHttpClientConnectionManager directly (Source). And those values also have been changed over the years ... But as said, Spring Boot uses HttpClientBuilder which has its own defaults.Gorge
@Volodymyr Kret did you find any reference in the Spring implementation to the setting of these 2 values? Or has Spring changed the strategy since 2018?Shiver
@DanielPop I was looking for these 2 configs in documentation, but no luck:( You can try to set them as env variables, though it isn't the best practiceEnsemble
it uses Apache HttpClient for pooling if included in your dependencies and RestTemplateBuilder was used in a correct way! If you have performance issues during establishing http connections I would always debug in detail if everything is working correctlyEthnogeny
Also check ClientHttpRequestFactorySupplier - it's default request factory for rest template builder. Likely you will receive apache http pool with 5 connections only.Ensemble
B
37

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

Brobdingnagian answered 25/5, 2017 at 20:46 Comment(5)
Do I need to create my resttemplate beans as prototype if I use pool?Indiaindiaman
@EugeneMakarenko No. How many instances of RestTemplate are you planning to instantiate?Brobdingnagian
I need 10 RestTemplates for each service for data transfer and 5 RestTemplates for authentication service. Do I need to inject these beans into my services as singletons or to create using the prototype scope per each request if I am going to use the connection pool from your article? I don't understand how the pool will return used RestTemplate back.Indiaindiaman
@EugeneMakarenko, why would you need 10 instances? RestTemplate is thread-safe. You can use the same RestTemplate instance to send requests to multiple services. Just configure it properly so that one slow service won't hijack the whole pool.Brobdingnagian
thank you! I was wrong. I have another question. I use two types of RestTemplates. The first is configured for authorization and the second uses for data receiving. Can I use one connection pool for them?Indiaindiaman
T
20

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.

Timisoara answered 15/1, 2021 at 13:13 Comment(3)
I really like your solution and I'd like to suggest 2 improvements: 1. Use RestTemplateBuilder 2. Also set setConnectTimeout() May I edit your answer or should I better post a separate answer?Frantic
Please update if needed, always welcome suggestions and improvementsTimisoara
I recommend to set a small ConnectionRequestTimeout (e.g. 100ms). This is the time until the client waits to get a connection from the pool. If it does not get a connection within 100ms an exception is thrown. In some cases this might be a simple replacement to an extra circuit breaker. What do others think?Frantic
O
19

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())
Osteoma answered 25/5, 2017 at 20:11 Comment(1)
Actually, not that simple. Connection pools per each RestTemplate are there: HttpComponentsClientHttpRequestFactory->HttpClients.createSystem()->HttpClientBuilder->PoolingHttpClientConnectionManagerEnsemble
M
3

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.

Mcarthur answered 7/10, 2022 at 10:25 Comment(0)
D
1

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/

Dunlin answered 12/10, 2019 at 2:50 Comment(1)
Indeed, OkHttp is a nice alternative implementation. Also the feature set is different. E. g. if you need a Read Timeout, that's not feasible with Apache HttpClient (https://mcmap.net/q/327721/-apache-httpclient-timeout), but it is with OkHttp. Apache's Client might have unique features too. In every case it's widely used - so to say "battle tested".Gorge

© 2022 - 2024 — McMap. All rights reserved.