配置SSLConnectionSocketFactory后RestTemplate并行请求受限问题求助
解决SSL RestTemplate的并行请求限制问题
我一眼就看出问题所在了——你自定义的HttpClient用了默认的连接池配置,而它的默认最大并发连接数只有2,这就是为啥同一时间只能有2个请求得到响应。而默认RestTemplate用的是SimpleClientHttpRequestFactory,它不会复用连接,每次请求都新建连接,所以没有这个限制。
要在保留SSL上下文的前提下实现多请求并行,只需要给HttpClient配置合理的连接池参数就行,具体步骤如下:
1. 配置连接池管理器
首先创建PoolingHttpClientConnectionManager,设置全局最大连接数和单路由最大连接数(可根据你的业务需求调整数值):
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); // 设置全局最大连接数,比如20 connectionManager.setMaxTotal(20); // 设置单个目标服务的最大连接数,比如10 connectionManager.setDefaultMaxPerRoute(10);
2. 将连接池管理器绑定到HttpClient
在构建HttpClient的时候,把上面的连接池管理器传进去,同时保留你的SSL配置:
HttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(socketFactory) .setConnectionManager(connectionManager) // 关键:添加连接池管理器 .build();
完整的修改后代码
把这些整合到你的createSSLRestTemplate方法里,最终代码如下:
private RestTemplate createSSLRestTemplate(String keyStorePath, String keyStorePassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(new ClassPathResource(keyStorePath).getInputStream(), keyStorePassword.toCharArray()); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( new SSLContextBuilder() .loadTrustMaterial(null, new TrustSelfSignedStrategy()) .loadKeyMaterial(keyStore, keyStorePassword.toCharArray()) .build(), NoopHostnameVerifier.INSTANCE); // 新增连接池配置 PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(20); // 全局最大连接数 connectionManager.setDefaultMaxPerRoute(10); // 单路由最大连接数 // 可选:设置连接闲置超时,30秒无活动则关闭 connectionManager.setValidateAfterInactivity(30000); HttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(socketFactory) .setConnectionManager(connectionManager) // 绑定连接池 .build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); BufferingClientHttpRequestFactory bufferingRequestFactory = new BufferingClientHttpRequestFactory(requestFactory); RestTemplate restTemplate = new RestTemplate(bufferingRequestFactory); restTemplate.setInterceptors(Collections.singletonList(restTemplateLoggingInterceptor)); return restTemplate; }
额外提示
- 不要盲目把连接数设置过大,要结合目标服务的承载能力调整,避免给对方造成压力。
- 如果你的系统需要调用多个不同的外部服务,可以针对特定路由单独设置最大连接数,比如:
HttpHost targetHost = new HttpHost("example.com", 443, "https"); connectionManager.setMaxPerRoute(new HttpRoute(targetHost), 15);
这样修改后,你的SSL RestTemplate就能像默认版本一样支持多请求并行发送了。
内容的提问来源于stack exchange,提问作者Udara S.S Liyanage
相关产品推荐
相关产品推荐

