2 Commits

Author SHA1 Message Date
  WangGuangYuan 419d4e2b36 Merge branch 'feature/agg' of http://git.ht-atia.cn/qinyanlei/inspect into feature/agg 2 weeks ago
  WangGuangYuan 9f42c6fc59 perf: 汇聚层访问站端改用 HTTP 连接池 2 weeks ago
5 changed files with 72 additions and 5 deletions
Split View
  1. +5
    -0
      inspect-main/inspect-main-agg/pom.xml
  2. +8
    -0
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java
  3. +44
    -5
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java
  4. +13
    -0
      inspect-main/inspect-main-agg/src/main/resources/application.yml
  5. +2
    -0
      pom.xml

+ 5
- 0
inspect-main/inspect-main-agg/pom.xml View File

@ -31,6 +31,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 用连接池复用 TCP 连接 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.inspect</groupId>
<artifactId>inspect-base-core</artifactId>


+ 8
- 0
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/AggProperties.java View File

@ -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


+ 44
- 5
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/config/RestTemplateConfig.java View File

@ -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 解码)。
*
* <p>聚合层向站端发起的起流/停流请求在打开多画面时会同时出现十几个,串行新建 TCP
* 连接会明显放大延迟并让部分请求打满页面 8 秒超时;这里改为复用连接的连接池。</p>
*/
@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<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> converter : converters) {
@ -41,4 +80,4 @@ public class RestTemplateConfig {
}
return restTemplate;
}
}
}

+ 13
- 0
inspect-main/inspect-main-agg/src/main/resources/application.yml View File

@ -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}

+ 2
- 0
pom.xml View File

@ -11,6 +11,8 @@
<properties>
<revision>3.4.0</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<java.version>1.8</java.version>


Loading…
Cancel
Save