超級簡單易用的 Spring RestTemplate, 還能夠多線程共享一個實例, 有一個小缺憾, 就是須要記得設置默認超時時間, 不然默認不超時. 而設置超時時間之後, 又會引入新的 Connection Pool 大小的問題.java
這個連接講了兩種方式:spring-resttemplate-timeout, 這裏就直接貼過來了web
@Configuration public class AppConfig{ @Bean public RestTemplate customRestTemplate(){ HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setConnectionRequestTimeout(...); httpRequestFactory.setConnectTimeout(...); httpRequestFactory.setReadTimeout(...); return new RestTemplate(httpRequestFactory); } }
@Bean public RestTemplate restTemplate( RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(500) .setReadTimeout(500) .build(); }
(不建議) 之前見過, 經過 property 設置全局 java.net 裏 URL 的 timeout 來影響 RestTemplate 的超時時間(默認使用java.net包裏面組件).spring
調用 RestTemplate 的默認構造函數,RestTemplate 對象在底層經過使用 java.net 包下的實現建立 HTTP 請求. 這種狀況相對簡單, 一個請求一個鏈接, 也沒有限制.多線程
而上面所說的前兩種設置超時方式, 都會致使 RestTemplate 引入 Apache HttpClient 去設置超時時間. 在默認 HttpClientBuilder
(httpClient-4.5.2)裏面有一段代碼:app
if (systemProperties) { String s = System.getProperty("http.keepAlive", "true"); if ("true".equalsIgnoreCase(s)) { s = System.getProperty("http.maxConnections", "5"); final int max = Integer.parseInt(s); poolingmgr.setDefaultMaxPerRoute(max); poolingmgr.setMaxTotal(2 * max); } }
在 keepAlive(默認) 狀況下, 默認設置了對單個 host 的最大 connection 數量是 5. 全部connection數量不能超過 10~ 若是說單個 host 設置長鏈接數設置爲5問題不大的話, 那麼對於須要訪問多個不一樣網站的狀況下, 鏈接總數一共10個就有點坑了. 在長時間得不到Connection的狀況下, 會拋出異常: org.springframework.web.client.ResourceAccessException Timeout waiting for connection from pool
函數
具體解決方法是手工配置一下鏈接池:性能
@Configuration public class RestTemplateConfig { @Value("${application.http.resttemplate.timeoutSeconds:30}") private Integer defaultTimeOutSeconds; @Value("${application.http.resttemplate.maxConnPerRoute:50}") private Integer defaultMaxPerRoute; @Value("${application.http.resttemplate.maxConnTotal:200}") private Integer maxTotal; @Bean public RestTemplate customRestTemplate() { int timeoutMills = defaultTimeOutSeconds * 1000; RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeoutMills) .setConnectionRequestTimeout(timeoutMills).setSocketTimeout(timeoutMills).build(); HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(maxTotal) .setMaxConnPerRoute(defaultMaxPerRoute).setDefaultRequestConfig(requestConfig).build(); HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory( httpClient); return new RestTemplate(httpRequestFactory); } }
具體大小適狀況而定. 鏈接總數配置過大還會影響性能.網站