RestTemplate 的配置和使用
Wenhao Wang 2020-07-23 Spring BootRestTemplate
Spring Boot 中 RestTemplate 配置及使用
# 1.配置
# 1.使用OKHttp
添加
OkHttp
依赖<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp-version}</version> </dependency>
1
2
3
4
5
# 2.添加配置类
配置方式1:不使用连接池
package com.leng.urlconversion.config; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; /** * @author wangwenhao * @description Http请求配置类 * @date 2020-04-22 14:00 */ @Configuration public class RestTemplateConfig { @Bean(name = "restTemplate") public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder) { RestTemplate restTemplate = restTemplateBuilder.build(); OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(); okHttp3ClientHttpRequestFactory.setReadTimeout(5000); okHttp3ClientHttpRequestFactory.setConnectTimeout(5000); restTemplate.setRequestFactory(okHttp3ClientHttpRequestFactory); restTemplate.getMessageConverters().stream() .filter(converter -> converter instanceof StringHttpMessageConverter) .findFirst() .ifPresent(stringMessageConverter -> ((StringHttpMessageConverter)stringMessageConverter).setDefaultCharset(StandardCharsets.UTF_8)); return restTemplate; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35配置方式2:使用连接池
package com.leng.urlconversion.config; import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; /** * @author wangwenhao * @description Http请求配置类 * @date 2020-04-22 14:00 */ @Configuration public class RestTemplateConfig { @Bean(name = "restTemplate") public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder) { RestTemplate restTemplate = restTemplateBuilder .requestFactory(this::getOkHttp3ClientHttpRequestFactory) .build(); restTemplate.getMessageConverters().stream() .filter(converter -> converter instanceof StringHttpMessageConverter) .findFirst() .ifPresent(stringMessageConverter -> ((StringHttpMessageConverter)stringMessageConverter).setDefaultCharset(StandardCharsets.UTF_8)); return restTemplate; } /** * 配置OKHttp的具体配置 * @return 连接工厂 */ public OkHttp3ClientHttpRequestFactory getOkHttp3ClientHttpRequestFactory() { OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectionPool(new ConnectionPool(200, 5, TimeUnit.MINUTES)) .build(); return new OkHttp3ClientHttpRequestFactory(okHttpClient); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46连接池配置:供参考
client = new OkHttpClient.Builder() .dispatcher(new Dispatcher(executorService)) .connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDurationMills, TimeUnit.MILLISECONDS)) .readTimeout(readTimeoutMills, TimeUnit.MILLISECONDS) .connectTimeout(connectTimeoutMills, TimeUnit.MILLISECONDS) .writeTimeout(writeTimeoutMills, TimeUnit.MILLISECONDS) .protocols(Util.immutableList(Protocol.HTTP_1_1)) .connectionSpecs(Arrays.asList(TLS_SPEC, ConnectionSpec.CLEARTEXT)) .build(); client.dispatcher().setMaxRequests(maxRequests); client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
1
2
3
4
5
6
7
8
9
10
11- maxRequests和maxReuestsPerHost值的设置与executorService线程池的设置有关联,请注意。maxRequests和maxRequestPerHost是okhttp内部维持的请求队列,而executorservice是实际发送请求的线程。如果maxRequests和maxReuestPerHost设置太大,executorService会因为线程太少而阻塞发送。
参数 意义 推荐值 executorService 内部执行http请求的实际线程池 默认 executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
没有常驻线程,性能低,线程没有限制上限。maxIdleConnections 连接池大小,指单个okhttpclient实例所有连接的连接池。 默认:5,值的设置与业务请求量有关,如果请求三方的tps是200,建议这个值设置在200左右。 keepAliveDurationMills 连接池中连接的最大时长 默认5分钟,依据业务场景来确定有效时间,如果不确定,那就保持5分钟 connectTimeoutMills 连接的最大超时时间 默认10秒 readTimeoutMills 读超时 默认10秒,如果是流式读,那建议设置长一点时间。 writeTimeoutMills 写超时 默认10秒,如果是流式写,那建议设置长一点时间 maxRequestPerHost 单个主机最大请求并发数,这里的主机指被请求方主机,一般可以理解对调用方有限流作用。注意:websocket请求不受这个限制。 默认:4,一般建议与maxRequest保持一致。这个值设置,有如下几个场景考虑:(1)如果被调用方的并发能力只能支持200,那这个值最好不要超过200,否则对调用方有压力;(2)如果当前okhttpclient实例只对一个调用方发起调用,那这个值与maxRequests保持一致;(3)如果当前okhttpclient实例在一个事务中对n个调用方发起调用,n * maxReuestPerHost要接近maxRequest maxRequests 当前okhttpclient实例最大的并发请求数 默认:64,默认的64一般满足不了业务需要。这个值一般要大于maxRequestPerHost,如果这个值小于maxRequestPerHost会导致,请求单个主机的并发不可能超过maxRequest.