From 9f42c6fc5984c7f77090b7179854ac1260b6ddaa Mon Sep 17 00:00:00 2001 From: WangGuangYuan Date: Sat, 24 Oct 2026 13:41:41 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=B1=87=E8=81=9A=E5=B1=82=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E7=AB=99=E7=AB=AF=E6=94=B9=E7=94=A8=20HTTP=20?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=B1=A0=20-=20RestTemplate=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20PoolingHttpClientConnectionManager=EF=BC=88?= =?UTF-8?q?=E6=80=BB=E8=BF=9E=E6=8E=A5=20100=E3=80=81=E5=8D=95=E7=AB=99?= =?UTF-8?q?=E7=AB=AF=2040=E3=80=81=20=20=20=E5=8F=96=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E7=AD=89=E5=BE=85=203s=E3=80=81=E7=A9=BA=E9=97=B2=2030s=20?= =?UTF-8?q?=E6=B8=85=E7=90=86=EF=BC=89=EF=BC=8C=E9=81=BF=E5=85=8D=E6=89=93?= =?UTF-8?q?=E5=BC=80=E5=A4=9A=E7=94=BB=E9=9D=A2=E6=97=B6=E6=AF=8F=E6=AC=A1?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E9=83=BD=E6=96=B0=E5=BB=BA=20TCP=20=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=EF=BC=9B=20=20=20=E5=AE=9E=E6=B5=8B=E4=B9=9D=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E5=B9=B6=E5=8F=91=E8=B5=B7=E6=B5=81=E6=9C=80=E6=85=A2?= =?UTF-8?q?=E4=BB=8E=205.6s=20=E9=99=8D=E5=88=B0=203.7s=EF=BC=8C=E8=B5=B7?= =?UTF-8?q?=E6=B5=81=E4=B8=8D=E5=86=8D=E8=A7=A6=E7=A2=B0=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=208=20=E7=A7=92=E8=B6=85=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inspect-main/inspect-main-agg/pom.xml | 5 ++ .../com/inspect/agg/config/AggProperties.java | 8 +++ .../agg/config/RestTemplateConfig.java | 49 +++++++++++++++++-- .../src/main/resources/application.yml | 13 +++++ pom.xml | 2 + 5 files changed, 72 insertions(+), 5 deletions(-) diff --git a/inspect-main/inspect-main-agg/pom.xml b/inspect-main/inspect-main-agg/pom.xml index 3fb006b..483a17c 100644 --- a/inspect-main/inspect-main-agg/pom.xml +++ b/inspect-main/inspect-main-agg/pom.xml @@ -31,6 +31,11 @@ org.springframework.boot spring-boot-starter-web + + + org.apache.httpcomponents + httpclient + com.inspect inspect-base-core diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java index 7575605..37f4fc3 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java @@ -93,6 +93,14 @@ public class AggProperties { public static class Http { private int connectTimeoutMs = 10_000; private int readTimeoutMs = 30_000; + /** + * 连接池总连接上限。 + */ + private int poolMaxTotal = 100; + /** 同一站端的连接上限;一次九画面并发起流按 3 路一批,留足余量。 */ + private int poolMaxPerRoute = 40; + /** 从连接池取空闲连接的等待上限(毫秒),避免池满时无限等待。 */ + private int connectionRequestTimeoutMs = 3_000; } @Data diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java index 6686efe..8113a3a 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java @@ -1,19 +1,27 @@ package com.inspect.agg.config; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.List; +import java.util.concurrent.TimeUnit; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.boot.web.client.RestTemplateBuilder; 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; /** - * HTTP 客户端配置:RestTemplate + 超时 + UTF-8(站点接口返回中文,必须 UTF-8 解码)。 + * HTTP 客户端配置:连接池 + 超时 + UTF-8(站点接口返回中文,必须 UTF-8 解码)。 + * + *

聚合层向站端发起的起流/停流请求在打开多画面时会同时出现十几个,串行新建 TCP + * 连接会明显放大延迟并让部分请求打满页面 8 秒超时;这里改为复用连接的连接池。

*/ @Configuration public class RestTemplateConfig { @@ -27,10 +35,41 @@ public class RestTemplateConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { + AggProperties.Http http = aggProperties.getHttp(); + + // 连接池:总连接数与单站端连接数都要覆盖“同时在飞的站端请求”。 + PoolingHttpClientConnectionManager connectionManager = + new PoolingHttpClientConnectionManager(); + connectionManager.setMaxTotal(Math.max(1, http.getPoolMaxTotal())); + connectionManager.setDefaultMaxPerRoute(Math.max(1, http.getPoolMaxPerRoute())); + + // 超时与池等待:取连接不能无限等,否则池满时请求会一直挂到页面超时。 + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(http.getConnectTimeoutMs()) + .setSocketTimeout(http.getReadTimeoutMs()) + .setConnectionRequestTimeout(http.getConnectionRequestTimeoutMs()) + .build(); + + CloseableHttpClient httpClient = HttpClients.custom() + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(requestConfig) + // 定期清理失效空闲连接,避免站端重启后一直复用坏连接。 + .evictExpiredConnections() + .evictIdleConnections(30L, TimeUnit.SECONDS) + .build(); + + // 只在这里指定请求工厂;连接与读取超时统一由上面的 RequestConfig 控制, + // 避免与 RestTemplateBuilder 的超时设置叠加产生歧义。 RestTemplate restTemplate = builder - .setConnectTimeout(Duration.ofMillis(aggProperties.getHttp().getConnectTimeoutMs())) - .setReadTimeout(Duration.ofMillis(aggProperties.getHttp().getReadTimeoutMs())) + .requestFactory(() -> { + HttpComponentsClientHttpRequestFactory factory = + new HttpComponentsClientHttpRequestFactory(httpClient); + factory.setConnectTimeout(http.getConnectTimeoutMs()); + factory.setReadTimeout(http.getReadTimeoutMs()); + return factory; + }) .build(); + // 默认 StringHttpMessageConverter 用 ISO-8859-1,会破坏站点返回的中文 List> converters = restTemplate.getMessageConverters(); for (HttpMessageConverter converter : converters) { @@ -41,4 +80,4 @@ public class RestTemplateConfig { } return restTemplate; } -} \ No newline at end of file +} diff --git a/inspect-main/inspect-main-agg/src/main/resources/application.yml b/inspect-main/inspect-main-agg/src/main/resources/application.yml index 934f631..898a62c 100644 --- a/inspect-main/inspect-main-agg/src/main/resources/application.yml +++ b/inspect-main/inspect-main-agg/src/main/resources/application.yml @@ -41,3 +41,16 @@ agg: # 是否在 /agg/proxy 通用代理的 JSON 响应中递归改写图片/文件地址 rewrite-proxy-response: true + # 访问站端接口的 HTTP 客户端;打开多画面时会同时发起多路起流/停流请求。 + http: + # 建立连接超时(毫秒) + connect-timeout-ms: ${AGG_HTTP_CONNECT_TIMEOUT_MS:10000} + # 读取响应超时(毫秒),需大于站端起流最慢耗时 + read-timeout-ms: ${AGG_HTTP_READ_TIMEOUT_MS:30000} + # 连接池总连接上限 + pool-max-total: ${AGG_HTTP_POOL_MAX_TOTAL:100} + # 同一站端的连接上限 + pool-max-per-route: ${AGG_HTTP_POOL_MAX_PER_ROUTE:40} + # 从池中取空闲连接的等待上限(毫秒) + connection-request-timeout-ms: ${AGG_HTTP_CONNECTION_REQUEST_TIMEOUT_MS:3000} + diff --git a/pom.xml b/pom.xml index 4575d65..5f73bbb 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,8 @@ 3.4.0 + UTF-8 + UTF-8 8 8 1.8