yaml配置类
# http线程池
http-pool:
# 一个服务每次能并行接收的请求数量
maxPerRoute: 200
# 服务一次最多接收的请求数量
maxTotal: 1000
# 从连接池获取连接
connectionRequestTimeout: 10000
# 连接超时
connectTimeout: 5000
# 数据读取超时时间
socketTimeout: 10000
# 最大存活时间(单位:分钟)
maxIdleTime: 5
@Configuration
public class ClientHttpPoolConfiguration {
@Autowired
private HttpConnectionPoolConfiguration poolConfiguration;
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setDefaultMaxPerRoute(poolConfiguration.getMaxPerRoute());
result.setMaxTotal(poolConfiguration.getMaxTotal());
return result;
}
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom()
.setConnectionRequestTimeout(poolConfiguration.getConnectionRequestTimeout())
.setConnectTimeout(poolConfiguration.getConnectTimeout())
.setSocketTimeout(poolConfiguration.getSocketTimeout())
.build();
}
@Bean
public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager, RequestConfig requestConfig) {
return HttpClientBuilder
.create()
.setConnectionManager(poolingHttpClientConnectionManager)
// 配置RestTemplate以允许重定向
.setRedirectStrategy(new LaxRedirectStrategy())
.setDefaultRequestConfig(requestConfig)
.evictExpiredConnections().evictIdleConnections(poolConfiguration.getMaxIdleTime(), TimeUnit.MINUTES)
// KeepAlive策略 连接超过20s没有数据就主动断开与服务器的连接
.setKeepAliveStrategy((response, context) -> Arrays.stream(response.getHeaders(HTTP.CONN_KEEP_ALIVE))
.filter(h -> StringUtils.equalsIgnoreCase(h.getName(), "timeout")
&& StringUtils.isNumeric(h.getValue()))
.findFirst()
.map(h -> NumberUtils.toLong(h.getValue(), 20))
.orElse(20L) * 1000)
.build();
}
}
@Component
@ConfigurationProperties(prefix = "http-pool")
@Data
public class HttpConnectionPoolConfiguration {
/**
* 一个服务每次能并行接收的请求数量
*/
private Integer maxPerRoute;
/**
* 服务一次最多接收的请求数量
*/
private Integer maxTotal;
/**
* 从连接池获取连接
*/
private Integer connectionRequestTimeout;
/**
* 连接超时
*/
private Integer connectTimeout;
/**
* 数据读取超时时间
*/
private Integer socketTimeout;
/**
* 最大存活时间
*/
private Integer maxIdleTime;
}
@Configuration
@Slf4j
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new
HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
// 支持中文编码
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
restTemplate.setErrorHandler(new MyResponseErrorHandler());
return restTemplate;
}
}
@Slf4j
public class MyResponseErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
response.close();
log.error("RestTemplate错误:url:{}, method:{},statusCode:{}", url.getPath(), method.name(), response.getStatusCode());
this.handleError(response);
}
}