通过 RestTemplateBuilder 的方式生成 RestTemplate
@Bean(name = "template")
RestTemplate template(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
//单位s, 设置连接时间,避免线程过多被阻塞挂起
.setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1))
.additionalMessageConverters(new MyMappingJackson2HttpMessageConverter())
.requestFactory(() -> {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
// 连接池
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//设置HTTP连接管理器
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
poolingConnectionManager.setMaxTotal(500); // 连接池最大连接数
poolingConnectionManager.setDefaultMaxPerRoute(200); // 每个主机的并发
httpClientBuilder.setConnectionManager(poolingConnectionManager);
// 设置 RequestConfig 连接池请求全局配置
// 连接池超时时间 3500ms
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(3500).build();
httpClientBuilder.setDefaultRequestConfig(requestConfig);
// 设置连接池
clientHttpRequestFactory.setHttpClient(httpClientBuilder.build());
return clientHttpRequestFactory;
})
.build();
}
restTemplate的连接由 RequestFactory 创建
HttpComponentsClientHttpRequestFactory 是 RequestFactory 实现类,连接池化,有 httpClient 引用
RestTemplateBuilder 用于生成 restTeamplte
configure 方法初始化了 RequestFactory 对象通过 buildRequestFactory
public ClientHttpRequestFactory buildRequestFactory() {
ClientHttpRequestFactory requestFactory = null;
if (this.requestFactory != null) {
requestFactory = (ClientHttpRequestFactory)this.requestFactory.get();
} else if (this.detectRequestFactory) {
// 默认连接池工厂
requestFactory = (new ClientHttpRequestFactorySupplier()).get();
}
if (requestFactory != null && this.requestFactoryCustomizer != null) {
this.requestFactoryCustomizer.accept(requestFactory);
}
return requestFactory;
}
超时参数说明:
- ConnectionRequestTimeout: 从连接池获取到连接的超时时间,常用于PoolingHttpClientConnectionManager(4.5),(4.3前MultiThreadedHttpConnectionManager)
- ReadTimeout:客户端与服务器已经建立连接后等待响应时间
- ConnectTimeout:建立连接(TCP)的超时时间
理论上请求的最长时间=以上三个参数的和,时间上请求的最长时间大部分在ReadTimeout+ConnectionRequestTimeout
若不配置ConnectionRequestTimeout可能会导致请求阻塞,该值默认-1,因为MaxPerRoute默认2,MaxTotal默认20,吞吐量上不去接口超时。