RestTemplate发起POST请求遇Connection pool shut down异常求助
RestTemplate 出现 Connection pool shut down 异常的解决方案
问题描述
使用RestTemplate发起POST请求时抛出以下异常:
Caused by: java.lang.IllegalStateException: Connection pool shut down at org.apache.http.util.Asserts.check(Asserts.java:34) ~[httpcore-4.4.15.jar:4.4.15] at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:269) ~[httpclient-4.5.13.jar:4.5.13] ...
当前使用httpclient:4.5.13,通过RestTemplateBuilder默认构建RestTemplate,未手动管理连接池。重启服务后异常暂时消失,但处理一定量请求后会再次出现。
原因分析
- 默认连接池配置参数不合理,无法适配业务请求量,导致连接资源耗尽后触发连接池关闭逻辑;
- 存在连接泄漏,未正确释放请求连接,导致连接池资源被占满;
- 重复创建RestTemplate实例,生成多个独立连接池,最终资源耗尽;
- Spring上下文生命周期异常,导致连接池被提前销毁。
解决方案
1. 手动配置HttpClient连接池
通过自定义连接池参数,精准控制连接生命周期,避免默认配置的隐患:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { // 初始化连接池管理器 PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); // 设置最大总连接数,根据业务调整 connectionManager.setMaxTotal(200); // 设置单个路由的最大连接数 connectionManager.setDefaultMaxPerRoute(50); // 配置请求超时参数 RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000) // 建立连接超时时间(ms) .setSocketTimeout(10000) // 读取响应超时时间(ms) .setConnectionRequestTimeout(5000) // 从连接池获取连接的超时时间(ms) .build(); // 构建HttpClient,添加连接池清理策略 CloseableHttpClient httpClient = HttpClientBuilder.create() .setConnectionManager(connectionManager) .setDefaultRequestConfig(requestConfig) .evictIdleConnections(30, TimeUnit.SECONDS) // 定期清理30秒空闲的连接 .evictExpiredConnections() // 清理过期连接 .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); return new RestTemplate(requestFactory); } }
之后在业务类中直接注入该单例RestTemplate即可:
@Autowired public ClientImpl(RestTemplate restTemplate) { this.restTemplate = restTemplate; }
2. 排查并修复连接泄漏
- 确保所有RestTemplate请求都在异常处理范围内,避免因未捕获异常导致连接无法释放:
try { restTemplate.postForObject(url, request, responseType); } catch (RestClientException e) { // 异常处理逻辑 log.error("请求失败", e); } - 开启HttpClient调试日志,跟踪连接状态:将
org.apache.http的日志级别设为DEBUG,查看连接的创建、释放情况,定位未释放的连接来源。
3. 避免重复创建RestTemplate实例
禁止通过RestTemplateBuilder.build()每次创建新实例,确保RestTemplate在Spring容器中是单例Bean,避免生成多个独立连接池导致资源耗尽。
4. 排查Spring上下文生命周期问题
- 检查自定义Bean的销毁逻辑,确认没有误调用
PoolingHttpClientConnectionManager.shutdown()方法; - 确保连接池管理器由Spring容器管理,其生命周期与容器一致,避免手动提前销毁。
内容的提问来源于stack exchange,提问作者user09
相关产品推荐
相关产品推荐

