Search code examples
javaspring-bootapache-httpclient-4.xresttemplatesocketexception

Rest Template - No buffer space available (maximum connections reached?)


I'm using RestTemplate to execute concurrent HTTP requests. After some time, I start getting

java.net.SocketException: No buffer space available (maximum connections reached?)

  1. I know that this is related to sockets in TIME_WAIT status.
  2. I have tried installing Windows 7 fix, that most sources encourage.
  3. I configured RestTemplate to use HttpClient as follows:

    val httpClient = HttpClientBuilder.create()
                .setMaxConnPerRoute(properties.concurrencyLimit)
                .setMaxConnTotal(properties.concurrencyLimit)
                .build()
    return RestTemplate(HttpComponentsClientHttpRequestFactory(httpClient))
    
  4. I have tried to use billion other HttpClient configurations

  5. I have tried different amounts of concurrent requests between 20-100

Just before I was going to press Post your question button, my colleague found a solution, that doesn't make any sense to me:

 val httpClient = HttpClientBuilder.create()
            .setMaxConnPerRoute(properties.concurrencyLimit * 2)
            .setMaxConnTotal(properties.concurrencyLimit * 2)
            .build()
    return RestTemplate(HttpComponentsClientHttpRequestFactory(httpClient))

Basically, when I set connection pool twice as big as threads number, the whole thing works like a charm.

WHY? WHY DOESN'T FIRST CONFIGURATION WORK AND SECOND DOES?

All dependencies are managed by Spring Boot 1.4.0.RELEASE parent pom.


Solution

  • Connections are pooled based on a route. Since you have at least 2 routes, total number of connections should be at least 2 times of max connections per route. See also other related post And yes, I would suggest to make even conenctionPool per rote more then number of threads if you process your batch one by one or there is some async nature.(not exactly sure how you use concurrencyLimit)

    See except from here:

    PoolingHttpClientConnectionManager is a more complex implementation that manages a pool of client connections and is able to service connection requests from multiple execution threads. Connections are pooled on a per route basis. A request for a route for which the manager already has a persistent connection available in the pool will be serviced by leasing a connection from the pool rather than creating a brand new connection. 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.