Java rest模板&x2B;ConnectionPoolTimeoutException:等待来自池的连接的超时
在应用程序没有任何负载的情况下,我在生产中突然出现了这个错误 当我的代码尝试使用SpringREST模板发送PUT消息时,出现了这个问题 下面是我初始化restTemplate的代码Java rest模板&x2B;ConnectionPoolTimeoutException:等待来自池的连接的超时,java,spring,apache-httpclient-4.x,resttemplate,Java,Spring,Apache Httpclient 4.x,Resttemplate,在应用程序没有任何负载的情况下,我在生产中突然出现了这个错误 当我的代码尝试使用SpringREST模板发送PUT消息时,出现了这个问题 下面是我初始化restTemplate的代码 private static final RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); { List<HttpMessageConverter<?>&
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);
}
原因:org.apache.http.conn.ConnectionPoolTimeoutException:
等待来自池的连接超时
这个错误是自我描述的。您需要在生产中增加连接池-当前实现的HttpComponents客户端HttpRequestFactory
默认构造函数正在使用HttpClientBuilder
和.useSystemProperties()
我相信默认情况下会有5个连接。这适用于客户端,但不太可能是您在服务器环境中想要的。
你需要使用类似于
new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create()
.setMaxConnTotal(200)
.setMaxConnPerRoute(50)
.build()));
我建议将
HttpComponentsClientHttpRequestFactory
实例配置为在RestTemplate
的构造函数中传递,增加defaultMaxPerRoute
或maxPerRoute
对于请求超时的特定http路由,增加池大小是不够的,正如我在一篇评论中提到的,即使将poollighttpclientconnectionmanager.setMaxTotal()
设置为200,HttpComponentsClientHttpRequestFactory
使用defaultMaxPerRoute
值4,我猜可能是在尝试主机路由(方案、主机、端口)不劫持连接池)
我最近在博客上写了一篇关于使用
JMeter
和shell命令对超时请求进行故障排除的文章,并通过配置设置进行了修复。问题在于HTTP客户端连接没有关闭。对于每秒只有1个请求的服务,我也遇到了同样的问题
"exception":"org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool"
您需要添加一个finally块并关闭连接。我怀疑这是连接池大小的问题,因为我提到了这个问题是在非常低的负载下发生的,我们在对50个并发用户进行负载测试时没有遇到这个问题。但是,是的,我们将把池大小从5个增加到25个(4个服务器,即100个连接)@NullPointerException请同时设置超时值-可能是在连接失败的情况下需要几秒钟,因此它会退出池。@NullPointerException 30秒太高了-我可以想象,如果服务器位于地球的不同地区,则需要2-3秒。需要考虑的一点是,它不会无论池有多大,如果不设置.setMaxConnProute(),我认为默认情况下是4,它将只为同一主机使用4个连接,即使您可能还有196个连接处于空闲状态,我想这是为了防止主机劫持池。@BorisTreukhov不,这不是太高。有ConnectTimeout(建立连接需要多少时间)和ReadTimeout(请求完成需要多少时间)。如果我在拨号链接上读取10MB(仅举一个例子),那么30秒的ReadTimeout可能太低了。如果这是apache客户端的异常,并且我们使用的是RestTemplate包装器,怎么做?
new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create()
.setMaxConnTotal(200)
.setMaxConnPerRoute(50)
.build()));
...
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
...
httpConnPool:
maxTotal: 20
defaultMaxPerRoute: 20
maxPerRoutes:
-
scheme: http
host: localhost
port: 8800
maxPerRoute: 20
"exception":"org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool"