java RestTemplate + ConnectionPoolTimeoutException:等待来自池的连接超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31597696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RestTemplate + ConnectionPoolTimeoutException: Timeout waiting for connection from pool
提问by NullPointerException
I got this error all of a sudden in production while the application was not under any load.
当应用程序没有任何负载时,我在生产中突然出现此错误。
The issue happened when my code tries to send the PUT message using spring rest template
当我的代码尝试使用 spring rest 模板发送 PUT 消息时发生了问题
Here is the code how I am initialing the restTemplate
这是我如何初始化 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);
}
Call to PUT
调用 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)
}
Exception stacktrace
异常堆栈跟踪
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.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)
回答by ootero
I would suggest to configure HttpComponentsClientHttpRequestFactory
instance being passed in the constructor of RestTemplate
increasing defaultMaxPerRoute
or maxPerRoute
for the specific http route for which requests are timing out, increasing the pool size is not enough, as I mentioned in a comment, even if you set PoolingHttpClientConnectionManager.setMaxTotal()
to 200, HttpComponentsClientHttpRequestFactory
uses a defaultMaxPerRoute
of 4, my guess would be in an attempt for a host route (scheme, host, port) not to hiHyman the connection pool)
我建议配置HttpComponentsClientHttpRequestFactory
在RestTemplate
增加的构造函数中传递的实例defaultMaxPerRoute
或maxPerRoute
对于请求超时的特定 http 路由,增加池大小是不够的,正如我在评论中提到的,即使您设置PoolingHttpClientConnectionManager.setMaxTotal()
为 200,也HttpComponentsClientHttpRequestFactory
使用defaultMaxPerRoute
共 4 个,我的猜测是尝试使主机路由(方案、主机、端口)不劫持连接池)
...
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
...
application.yml
应用程序.yml
httpConnPool:
maxTotal: 20
defaultMaxPerRoute: 20
maxPerRoutes:
-
scheme: http
host: localhost
port: 8800
maxPerRoute: 20
I recently blog about Troubleshooting Spring's RestTemplate Requests Timeoutwhere requests timing out were troubleshooted using JMeter
and shell commands and fixed via configuration settings.
我最近写了一篇关于Spring 的 RestTemplate 请求超时故障排除的博客,其中请求超时使用JMeter
shell 命令进行故障排除并通过配置设置修复。
回答by Boris Treukhov
Caused by: org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
引起:org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
This error is self describing. You need to increase your connection pool in production - current implementation of HttpComponentsClientHttpRequestFactory
default constructor is using HttpClientBuilder
with .useSystemProperties()
.
这个错误是自我描述的。您需要在生产中增加连接池 -HttpComponentsClientHttpRequestFactory
默认构造函数的当前实现使用HttpClientBuilder
with .useSystemProperties()
。
I believe it will be 5 connections by default. This works for client but is unlikely what you want in server environment. You need to use something like
我相信默认情况下它将是 5 个连接。这适用于客户端,但在服务器环境中不太可能是您想要的。你需要使用类似的东西
new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create()
.setMaxConnTotal(200)
.setMaxConnPerRoute(50)
.build()));
回答by cwa
The problem is the HTTP client connections aren't being closed. I had the same problem with a service that only has about 1 request per second.
问题是 HTTP 客户端连接没有被关闭。我对每秒只有大约 1 个请求的服务遇到了同样的问题。
"exception":"org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool"
You need to add a finally block and close the connection.
您需要添加一个 finally 块并关闭连接。