About Me

My photo
Rohit is an investor, startup advisor and an Application Modernization Scale Specialist working at Google.

Friday, November 1, 2019

Spring RestTemplate Buyer Beware!

TL;DR Be vary of the default RestTemplate injected or manually configured in your existing application. You should leverage HTTP Connection pooling for the RestTemplate which may not be turned  on by default. You  can explicitly configure it with the code sample I provided above. Also the Pool defaults are undersized. change those to a number appropriate to your env.  I set them to max 20 per route. tune per load  also configure connection pool stale connection reaping. Instead of the RestTemplate as the Spring docs advise as of Spring Framework 5.0.

TL;DR based on the multiple enterprise engagements … 

  • The default HTTP client connx. pools must be changed before deploy
  • Don’t forget to set ConnectionRequestTimeout  (defaults to infinity)
  • If possible replace RestTemplate/HttpClient with WebClient, else migrate to okHttpClient which has resolved most observed issues;
  • okHttpClient  has excellent connection pool manager, connection failure and timeouts handling mechanisms..

For instance
    //Wont configure the PoolingHttpClientConnectionManager
    public RestTemplate restTemplate() {
        return new RestTemplate();

    // WILL configure the PoolingHttpClientConnectionManager
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();

For this to work you need to put HTTPClient or the okHttpclient library on the Classpath

Spring apps leverage the org.springframework.web.client.RestTemplate as a synchronous client to perform HTTP requests. The default configuration of the 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. This is a problem.  BasicHttpClientConnectionManager can be used for a Low Level, Single Threaded Connection

Under load Spring RestTemplate client connections are capped at 4 per route. This *blows up under load*. If you see `HTTP status 500` for requests or slow responses please check the HTTPClient configuration and visit the recommendations

## Recommendations
- If you need to have a connection pooling under rest template then you should use different implementation of the ClientHttpRequestFactory that pools the connections. new RestTemplate(new HttpComponentsClientHttpRequestFactory())

- Use the `PoolingHttpClientConnectionManager` to Get and Manage a Pool of Multithreaded Connections. The defaults of the pooling connection manager too small. You should bump UP the MaxTotal, DefaultMaxPerRoute & MaxPerRoute to 20.

- Maximize the utilization of the HTTP Conn Pool
  -  Implement a Custom Keep Alive Strategy
  -  Configure connection evictions to detect idle and expired connections and close them
 -  Read this article https://www.baeldung.com/httpclient-connection-management for connection management.

HttpClientConnectionManager poolingConnManager
  = new PoolingHttpClientConnectionManager();
CloseableHttpClient client
 = HttpClients.custom().setConnectionManager(poolingConnManager)

also see https://bitbucket.org/asimio/resttemplate-troubleshooting-svc-2/src/master/src/main/java/com/asimio/api/demo/main/ResttemplateTroubleshootingSvc2Application.java

 As of 5.0, the non-blocking, reactive org.springframework.web.reactive.client.WebClient offers a modern alternative to the RestTemplate with efficient support for both sync and async, as well as streaming scenarios. Always use the *Builder to either create a (or more) RestTemplate or WebClient. Dependencies like spring-cloud-sleuth use the customizer/builder resp.  to add additional features

For greenfield apps pick WebClient over RestTemplate. see

 **The RestTemplate will be deprecated in a future version and will not have major new features added going forward. See the WebClient section of the Spring Framework reference documentation for more details and example code**

## Miscellaneous

  1. For slow requests or for goRouter latency follow https://docs.pivotal.io/pivotalcf/2-5/adminguide/troubleshooting_slow_requests.html and Debugging the Cloud Foundry Routing Tier https://www.youtube.com/watch?v=U5GWgabsxXY
  2. If you encounter a customer that is experiencing an application performance issue (increased latency or decreased throughput or slow requests), try having them run this plugin against the app while it’s under load: https://github.com/cloudfoundry/cpu-entitlement-plugin.
  3. If your Application running on TAS is slow, performing poorly, experiencing high latency and/or decreased throughput then follow debug instructions here  https://community.pivotal.io/s/article/Application-running-on-TAS-is-slow-performing-poorly-experiencing-high-latency-and-or-decreased-throughput

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.