41

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

Sam
  • 861
  • 3
  • 10
  • 16

6 Answers6

39

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
Peter Wippermann
  • 4,125
  • 5
  • 35
  • 48
Volodymyr Kret
  • 1,511
  • 15
  • 16
  • 2
    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. – peerless-phreap Jan 26 '22 at 19:38
  • 3
    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](https://github.com/apache/httpcomponents-client/blob/6ba9b4acdcba411a035503e3eae9e17b64bcc59b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java#L110-L111)). And those values also have been changed over the years ... But as said, Spring Boot uses `HttpClientBuilder` which has its own defaults. – Peter Wippermann Jan 28 '22 at 08:01
  • @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? – Daniel Pop Jun 15 '23 at 06:58
  • 1
    @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 practice – Volodymyr Kret Jun 21 '23 at 11:29
30

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

ootero
  • 3,235
  • 2
  • 16
  • 22
  • Do I need to create my resttemplate beans as prototype if I use pool? – Eugene Makarenko Nov 23 '20 at 16:48
  • @EugeneMakarenko No. How many instances of RestTemplate are you planning to instantiate? – ootero Nov 23 '20 at 21:32
  • 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. – Eugene Makarenko Nov 24 '20 at 07:37
  • 2
    @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. – ootero Nov 24 '20 at 20:52
  • 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? – Eugene Makarenko Nov 25 '20 at 06:49
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())
Praneeth Ramesh
  • 3,434
  • 1
  • 28
  • 34
  • 7
    Actually, not that simple. Connection pools per each RestTemplate are there: HttpComponentsClientHttpRequestFactory->HttpClients.createSystem()->HttpClientBuilder->PoolingHttpClientConnectionManager – Volodymyr Kret Dec 31 '18 at 08:58
16

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.

Matthias M
  • 12,906
  • 17
  • 87
  • 116
sendon1982
  • 9,982
  • 61
  • 44
  • 2
    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? – Matthias M Jan 26 '21 at 06:06
  • Please update if needed, always welcome suggestions and improvements – sendon1982 Jan 27 '21 at 23:33
  • 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? – Matthias M Jan 28 '21 at 07:58
2

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.

HereAndBeyond
  • 794
  • 1
  • 8
  • 17
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/

Kishan B
  • 4,731
  • 1
  • 19
  • 11
  • 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://stackoverflow.com/a/6764373/193705), 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". – Peter Wippermann Sep 09 '21 at 12:53