summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortanghao <[email protected]>2024-05-17 10:08:11 +0800
committertanghao <[email protected]>2024-05-17 10:08:11 +0800
commit30fba0edb1b4b85117e15e9e728bd4dda39a79ce (patch)
tree37f962ce5224cabca1071f6cb35236690de5f3fc
parent1b3860c4ff1626ba953f615898c3773b10099b1d (diff)
fix: 优化resttemplate内部实现
-rw-r--r--cn-admin/src/main/java/net/geedge/common/config/RestTemplateConfig.java126
1 files changed, 116 insertions, 10 deletions
diff --git a/cn-admin/src/main/java/net/geedge/common/config/RestTemplateConfig.java b/cn-admin/src/main/java/net/geedge/common/config/RestTemplateConfig.java
index 4d2522b..f4be47f 100644
--- a/cn-admin/src/main/java/net/geedge/common/config/RestTemplateConfig.java
+++ b/cn-admin/src/main/java/net/geedge/common/config/RestTemplateConfig.java
@@ -1,8 +1,30 @@
package net.geedge.common.config;
import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
import java.util.List;
+import javax.net.ssl.SSLContext;
+
+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.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+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.apache.http.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
@@ -12,7 +34,7 @@ import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
@@ -21,11 +43,41 @@ import cn.hutool.log.Log;
@Configuration
public class RestTemplateConfig {
private static final Log log = Log.get();
- @Value("${restTemplate.readTimeout:30000}")
+ /*@Value("${restTemplate.readTimeout:30000}")
private int readTimeout;
@Value("${restTemplate.connectTimeout:300000}")
- private int connectTimeout;
-
+ private int connectTimeout;*/
+ /**
+ * # 从连接池获取连接的timeout,不宜过大,ms
+ */
+ @Value("${http-pool.connection-request-timeout:200}")
+ private int connectionRequestTimeout;
+ /**
+ * 指客户端和服务器建立连接的超时时间,ms , 最大约21秒,因为内部tcp在进行三次握手建立连接时,默认tcp超时时间是20秒
+ */
+ @Value("${http-pool.connection-timeout:10000}")
+ private int connectionTimeout;
+ /**
+ * 指客户端从服务器读取数据包的间隔超时时间,不是总读取时间,也就是socket timeout,ms
+ */
+ @Value("${http-pool.socket-timeout:60000}")
+ private int socketTimeout;
+ /**
+ * #每个路由的最大连接数,如果只调用一个地址,可以将其设置为最大连接数
+ */
+ @Value("${http-pool.max-per-route:10000}")
+ private int maxPerRoute;
+ /**
+ * #连接池的最大连接数,0代表不限;如果取0,需要考虑连接泄露导致系统崩溃的后果
+ */
+ @Value("${http-pool.max-total:1000}")
+ private int maxTotal;
+
+ /**
+ * 长连接保持时间 单位s,不宜过长
+ */
+ @Value("${http-pool.keep-alive-time:60}")
+ private int keepAliveTime;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder,ClientHttpRequestFactory factory,ResponseErrorHandler errorHandler){
RestTemplate restTemplate = builder.build();
@@ -63,13 +115,67 @@ public class RestTemplateConfig {
}
@Bean
- public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
- SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
- factory.setConnectTimeout(this.connectTimeout);
- factory.setReadTimeout(this.readTimeout);
- return factory;
- }
+ public ClientHttpRequestFactory httpRequestFactory(HttpClient client) {
+ return new HttpComponentsClientHttpRequestFactory(client);
+ }
+ @Bean
+ public HttpClient httpClient(ConnectionKeepAliveStrategy keepAliveStrategy) throws Exception {
+ //配置不校验server 证书
+ TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ return true;
+ }
+ };
+ SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
+ SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
+ .register("https", sslConnectionSocketFactory).build();
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
+ // 设置整个连接池最大连接数 根据自己的场景决定
+ connectionManager.setMaxTotal(maxTotal);
+ // 路由是对maxTotal的细分
+ connectionManager.setDefaultMaxPerRoute(maxPerRoute);
+ RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)// 服务器返回数据(response)的时间,超过该时间抛出readtimeout
+ .setConnectTimeout(connectionTimeout)// 连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
+ .setConnectionRequestTimeout(connectionRequestTimeout)// 从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException:Timeout
+ // waiting for connection from pool
+ .build();
+ return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager)
+ .setKeepAliveStrategy(keepAliveStrategy).build();
+ }
+
+ /**
+ * 配置长连接保持策略
+ *
+ * @return
+ */
+ @Bean
+ public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
+ return new ConnectionKeepAliveStrategy() {
+ @Override
+ public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
+ // Honor '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 && "timeout".equalsIgnoreCase(param)) {
+ try {
+ return Long.parseLong(value) * 1000;
+ } catch (NumberFormatException ignore) {
+ }
+ }
+ }
+ return keepAliveTime * 1000;
+ }
+ };
+ }
+
/**
* resttemplate 请求响应不抛出异常
* @return