import java.util.concurrent.TimeUnit; import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Autowired private RestTemplateProperties restTemplateProperties; @Bean public RestTemplate restTemplate() { return new RestTemplate(httpRequestFactory()); } @Bean public ClientHttpRequestFactory httpRequestFactory() { return new HttpComponentsClientHttpRequestFactory(httpClient()); } // pool監測線程,定期移除過期連接、空閑連接 /* public static class IdleConnectionMonitorThread extends Thread { private final HttpClientConnectionManager connMgr; public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) { super(); this.connMgr = connMgr; } @Override public void run() { try { while (true) { synchronized (this) { Thread.sleep(5000); connMgr.closeExpiredConnections(); connMgr.closeIdleConnections(5, TimeUnit.SECONDS); } } } catch (InterruptedException e) { e.printStackTrace(); } } } */ @Bean public HttpClient httpClient() { // 支持http和https Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()).build(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); connectionManager.setMaxTotal(restTemplateProperties.getMaxTotal()); connectionManager.setDefaultMaxPerRoute(restTemplateProperties.getDefaultMaxPerRoute()); connectionManager.setValidateAfterInactivity(restTemplateProperties.getValidateAfterInactivity()); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(restTemplateProperties.getConnectTimeout()) .setSocketTimeout(restTemplateProperties.getSocketTimeout()) .setConnectionRequestTimeout(restTemplateProperties.getConnectionRequestTimeout()).build(); // keep-alive策略 ConnectionKeepAliveStrategy keepAliveStrategy = new ConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse response, HttpContext context) { // 如果服務端response返回了Keep-Alive header HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { return Long.parseLong(value) * 1000; } catch (NumberFormatException ignore) { } } } // 否則設置客戶端默認keep-alive超時時間 return restTemplateProperties.getClientDefaultKeepAliveTime(); } }; /* Thread t = new IdleConnectionMonitorThread(connectionManager); t.setName("httpconnections-pool-evict-thread"); t.start(); */ return HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .evictExpiredConnections() //設置后台線程剔除失效連接 .evictIdleConnections(restTemplateProperties.getMaxIdleTime(), TimeUnit.MILLISECONDS) .setKeepAliveStrategy(keepAliveStrategy).build(); } }
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix="resttemplate") public class RestTemplateProperties { private Integer maxTotal; //總連接數 private Integer defaultMaxPerRoute; //單個路由最大連接數 private Integer connectTimeout; // 與遠程服務器建立連接的時間 private Integer connectionRequestTimeout; // 從connection manager獲取連接的超時時間 private Integer socketTimeout; // 建立連接之后,等待遠程服務器返回數據的時間,也就是兩個數據包(請求包和響應包)之間不活動的最大時間 private Integer validateAfterInactivity; private Integer clientDefaultKeepAliveTime; //客戶端默認keep-alive時間 private Integer maxIdleTime; //連接最大空閑時間 public Integer getMaxTotal() { return maxTotal; } public void setMaxTotal(Integer maxTotal) { this.maxTotal = maxTotal; } public Integer getDefaultMaxPerRoute() { return defaultMaxPerRoute; } public void setDefaultMaxPerRoute(Integer defaultMaxPerRoute) { this.defaultMaxPerRoute = defaultMaxPerRoute; } public Integer getConnectTimeout() { return connectTimeout; } public void setConnectTimeout(Integer connectTimeout) { this.connectTimeout = connectTimeout; } public Integer getConnectionRequestTimeout() { return connectionRequestTimeout; } public void setConnectionRequestTimeout(Integer connectionRequestTimeout) { this.connectionRequestTimeout = connectionRequestTimeout; } public Integer getSocketTimeout() { return socketTimeout; } public void setSocketTimeout(Integer socketTimeout) { this.socketTimeout = socketTimeout; } public Integer getValidateAfterInactivity() { return validateAfterInactivity; } public void setValidateAfterInactivity(Integer validateAfterInactivity) { this.validateAfterInactivity = validateAfterInactivity; } public Integer getClientDefaultKeepAliveTime() { return clientDefaultKeepAliveTime; } public void setClientDefaultKeepAliveTime(Integer clientDefaultKeepAliveTime) { this.clientDefaultKeepAliveTime = clientDefaultKeepAliveTime; } public Integer getMaxIdleTime() { return maxIdleTime; } public void setMaxIdleTime(Integer maxIdleTime) { this.maxIdleTime = maxIdleTime; } }
resttemplate.max-total=2000 resttemplate.default-max-per-route=1000 resttemplate.connect-timeout=5000 resttemplate.connection-request-timeout=1000 resttemplate.socket-timeout=5000 resttemplate.validate-after-inactivity=2000 resttemplate.client-default-keep-alive-time=5000 resttemplate.max-idle-time=5000
參考: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html