超级简单易用的 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); } }
具体大小适状况而定. 链接总数配置过大还会影响性能.网站