Skip to content

Instantly share code, notes, and snippets.

@soverby
Last active February 27, 2024 15:54
Show Gist options
  • Save soverby/0dbeab4d77b402e178eabb66a06407c0 to your computer and use it in GitHub Desktop.
Save soverby/0dbeab4d77b402e178eabb66a06407c0 to your computer and use it in GitHub Desktop.
RestTemplate backed by Apache HttpClient Connection Pool. Addresses RestTemplate HttpConnection exhaustion. Note this implementation is not route tunable and should be expanded when tuning by route is required. Example error: I/O error on POST request for "https://someendpoint": Timeout waiting for connection from pool; nested exception is org.a…
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ClientHttpPoolConfiguration {
@Autowired
private HttpConnectionPoolConfiguration poolConfiguration;
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setDefaultMaxPerRoute(poolConfiguration.getMaxPerRoute());
result.setMaxTotal(poolConfiguration.getMaxTotal());
return result;
}
@Bean
public RequestConfig requestConfig() {
RequestConfig result = RequestConfig.custom()
.setConnectionRequestTimeout(poolConfiguration.getConnectionRequestTimeout())
.setConnectTimeout(poolConfiguration.getConnectTimeout())
.setSocketTimeout(poolConfiguration.getSocketTimeout())
.build();
return result;
}
@Bean
public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager,
RequestConfig requestConfig) {
CloseableHttpClient result = HttpClientBuilder
.create()
.setConnectionManager(poolingHttpClientConnectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
return result;
}
}
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
import org.apache.http.client.HttpClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new
HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
restTemplate.setErrorHandler(new CustomErrorResponseHandler());
return restTemplate;
}
}
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "httppool")
@Data
public class HttpConnectionPoolConfiguration {
private Integer maxPerRoute;
private Integer maxTotal;
private Integer connectionRequestTimeout;
private Integer connectTimeout;
private Integer socketTimeout;
}
httppool:
maxPerRoute: 100
maxTotal: 1000
connectionRequestTimeout: 300
connectTimeout: 300
socketTimeout: 1500
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment