Nul*_*ion 3 java spring resttemplate apache-httpclient-4.x
在应用程序没有任何负载的情况下,我在生产过程中突然收到此错误.
当我的代码尝试使用spring rest模板发送PUT消息时,问题就出现了
这是我如何初始化restTemplate的代码
private static final RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
{
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(PaymentSession.class);
MarshallingHttpMessageConverter marshallingHttpMessageConverter = new MarshallingHttpMessageConverter(marshaller, marshaller);
marshallingHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_XML, MediaType.TEXT_HTML));
messageConverters.add(marshallingHttpMessageConverter);
restTemplate.setMessageConverters(messageConverters);
}
Run Code Online (Sandbox Code Playgroud)
致电PUT
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<PaymentSession> httpEntity = new HttpEntity<PaymentSession>(session, headers);
restTemplate.exchange(baseUrl+"/v1/psps", HttpMethod.PUT, httpEntity, PaymentSession.class);
}catch(HttpClientErrorException e){
logger.error("Exception..!!",e)
}
Run Code Online (Sandbox Code Playgroud)
异常堆栈跟踪
Caused by: org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
at org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection(PoolingClientConnectionManager.java:232)
at org.apache.http.impl.conn.PoolingClientConnectionManager$1.getConnection(PoolingClientConnectionManager.java:199)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:456)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:88)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:49)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:509)
Run Code Online (Sandbox Code Playgroud)
我建议配置HttpComponentsClientHttpRequestFactory在RestTemplate增加的构造函数中传递的实例,defaultMaxPerRoute或者maxPerRoute为请求超时的特定http路由传递,增加池大小是不够的,正如我在评论中提到的,即使你设置PoolingHttpClientConnectionManager.setMaxTotal()为200,也HttpComponentsClientHttpRequestFactory使用了defaultMaxPerRoute4,我的猜测是尝试主机路由(方案,主机,端口)不要劫持连接池)
...
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setMaxTotal(this.httpHostConfiguration.getMaxTotal());
// Default max per route is used in case it's not set for a specific route
result.setDefaultMaxPerRoute(this.httpHostConfiguration.getDefaultMaxPerRoute());
// and / or
if (CollectionUtils.isNotEmpty(this.httpHostConfiguration.getMaxPerRoutes())) {
for (HttpHostConfiguration httpHostConfig : this.httpHostConfiguration.getMaxPerRoutes()) {
HttpHost host = new HttpHost(httpHostConfig.getHost(), httpHostConfig.getPort(), httpHostConfig.getScheme());
// Max per route for a specific host route
result.setMaxPerRoute(new HttpRoute(host), httpHostConfig.getMaxPerRoute());
}
}
return result;
}
...
@Configuration
@ConfigurationProperties(prefix = "httpConnPool")
public class HttpHostsConfiguration {
private Integer maxTotal;
private Integer defaultMaxPerRoute;
private List<HttpHostConfiguration> maxPerRoutes;
// Getters, Setters
...
Run Code Online (Sandbox Code Playgroud)
application.yml
httpConnPool:
maxTotal: 20
defaultMaxPerRoute: 20
maxPerRoutes:
-
scheme: http
host: localhost
port: 8800
maxPerRoute: 20
Run Code Online (Sandbox Code Playgroud)
我最近在博客上讨论了Spring的RestTemplate请求超时问题,其中使用JMeter和shell命令对请求超时进行了故障排除,并通过配置设置进行了修复.
引起:org.apache.http.conn.ConnectionPoolTimeoutException:超时等待池连接
此错误是自我描述.你需要增加生产连接池-目前执行的HttpComponentsClientHttpRequestFactory默认构造函数使用HttpClientBuilder与.useSystemProperties().
我相信它默认是5个连接.这适用于客户端,但在服务器环境中不太可能.你需要使用类似的东西
new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create()
.setMaxConnTotal(200)
.setMaxConnPerRoute(50)
.build()));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13557 次 |
| 最近记录: |