|
@@ -0,0 +1,141 @@
|
|
|
+package com.hrsk.cloud.eg.infrastructure.client.http;
|
|
|
+
|
|
|
+import org.apache.http.HttpEntityEnclosingRequest;
|
|
|
+import org.apache.http.NoHttpResponseException;
|
|
|
+import org.apache.http.client.HttpRequestRetryHandler;
|
|
|
+import org.apache.http.client.protocol.HttpClientContext;
|
|
|
+import org.apache.http.config.Registry;
|
|
|
+import org.apache.http.config.RegistryBuilder;
|
|
|
+import org.apache.http.conn.ConnectTimeoutException;
|
|
|
+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.CloseableHttpClient;
|
|
|
+import org.apache.http.impl.client.HttpClientBuilder;
|
|
|
+import org.apache.http.impl.client.HttpClients;
|
|
|
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
|
+import org.apache.http.protocol.HttpContext;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.context.annotation.Bean;
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
|
|
+import org.springframework.http.converter.HttpMessageConverter;
|
|
|
+import org.springframework.http.converter.StringHttpMessageConverter;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.ConnectException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Author: zhangyy
|
|
|
+ * Date: 2019/3/20
|
|
|
+ * Description:
|
|
|
+ */
|
|
|
+@Configuration
|
|
|
+public class RetryRestTemplate {
|
|
|
+
|
|
|
+ @Value("${http.client.retryIntervalTime:0}")
|
|
|
+ private Long retryIntervalTime;
|
|
|
+
|
|
|
+ @Value("${http.client.connectTimeout:2500}")
|
|
|
+ private Integer connectTimeout;
|
|
|
+
|
|
|
+ @Value("${http.client.connectionRequestTimeout:1500}")
|
|
|
+ private Integer connectionRequestTimeout;
|
|
|
+
|
|
|
+ private RetryRequestConfig requestConfig = new RetryRequestConfig();
|
|
|
+
|
|
|
+ public RetryRestTemplate(RetryRequestConfig requestConfig) {
|
|
|
+ this.requestConfig = requestConfig;
|
|
|
+ }
|
|
|
+
|
|
|
+ public RetryRestTemplate() {
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 配置restTemplate
|
|
|
+ */
|
|
|
+ private void config(){
|
|
|
+ if(retryIntervalTime!=null){
|
|
|
+ requestConfig.setRetryIntervalTime(retryIntervalTime);
|
|
|
+ }
|
|
|
+ if(connectTimeout!=null){
|
|
|
+ requestConfig.setConnectTimeout(connectTimeout);
|
|
|
+ }
|
|
|
+ if(connectionRequestTimeout!=null){
|
|
|
+ requestConfig.setConnectionRequestTimeout(connectionRequestTimeout);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public RestTemplate restTemplate(){
|
|
|
+ RestTemplate restTemplate = new RestTemplate();
|
|
|
+ config();
|
|
|
+ //1.用UTF-8 StringHttpMessageConverter替换默认StringHttpMessageConverter
|
|
|
+ List<HttpMessageConverter<?>> newMessageConverters = new ArrayList<>();
|
|
|
+ for(HttpMessageConverter<?> converter : restTemplate.getMessageConverters()){
|
|
|
+ if(converter instanceof StringHttpMessageConverter){
|
|
|
+ StringHttpMessageConverter messageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
|
|
|
+ newMessageConverters.add(messageConverter);
|
|
|
+ }else {
|
|
|
+ newMessageConverters.add(converter);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ restTemplate.setMessageConverters(newMessageConverters);
|
|
|
+ //2. retryHandler add
|
|
|
+ HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
|
|
+ HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
|
|
|
+ @Override
|
|
|
+ public boolean retryRequest(IOException exception, int curRetryCount, HttpContext context) {
|
|
|
+ try {
|
|
|
+ //重试延迟
|
|
|
+ TimeUnit.SECONDS.sleep(curRetryCount*requestConfig.getRetryIntervalTime());
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ if (curRetryCount > requestConfig.getRetryCount()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (exception instanceof ConnectTimeoutException
|
|
|
+ || exception instanceof NoHttpResponseException || exception instanceof ConnectException) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ HttpClientContext clientContext = HttpClientContext.adapt(context);
|
|
|
+ org.apache.http.HttpRequest request = clientContext.getRequest();
|
|
|
+ boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
|
|
|
+ // 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的
|
|
|
+ return idempotent;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 3.支持HTTP、HTTPS
|
|
|
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
|
|
|
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
|
|
|
+ .register("https", SSLConnectionSocketFactory.getSocketFactory())
|
|
|
+ .build();
|
|
|
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
|
|
|
+ connectionManager.setMaxTotal(this.requestConfig.getConnectMaxTotal());
|
|
|
+ connectionManager.setDefaultMaxPerRoute(100);
|
|
|
+ connectionManager.setValidateAfterInactivity(2000);
|
|
|
+ httpClientBuilder.setRetryHandler(handler)
|
|
|
+ .setConnectionManager(connectionManager);
|
|
|
+
|
|
|
+ CloseableHttpClient httpClient = httpClientBuilder.build();
|
|
|
+ // httpClient连接配置,底层是配置RequestConfig
|
|
|
+ HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
|
|
+ // 连接超时
|
|
|
+ clientHttpRequestFactory.setConnectTimeout(this.requestConfig.getConnectTimeout());
|
|
|
+ // 数据读取超时时间,即SocketTimeout
|
|
|
+ clientHttpRequestFactory.setReadTimeout(this.requestConfig.getReadTimeout());
|
|
|
+ // 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
|
|
|
+ clientHttpRequestFactory.setConnectionRequestTimeout(this.requestConfig.getConnectionRequestTimeout());
|
|
|
+ // 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。
|
|
|
+ // clientHttpRequestFactory.setBufferRequestBody(false);
|
|
|
+ restTemplate.setRequestFactory(clientHttpRequestFactory);
|
|
|
+ return restTemplate;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|