9.2 KiB
并发性能优化总结
优化概述
本次优化主要针对提高系统并发处理能力,解决潜在的超时和阻塞问题。
主要优化内容
1. ✅ Tomcat 线程池优化(高优先级)
文件: src/main/resources/application.yml
优化项:
server:
tomcat:
threads:
max: 200 # 最大工作线程数(默认值为200)
min-spare: 20 # 最小空闲线程数(从默认10提升到20)
max-connections: 10000 # 最大连接数(从默认8192提升)
accept-count: 200 # 等待队列长度(从默认100提升)
connection-timeout: 20000 # 连接超时20秒
shutdown: graceful # 优雅关闭
效果:
- 支持更多并发 HTTP 请求
- 减少请求等待时间
- 优雅关闭避免请求中断
2. ✅ 数据库连接池优化(高优先级)
文件: src/main/resources/application.yml
优化项:
hikari:
maximum-pool-size: 100 # 从50增加到100
minimum-idle: 20 # 从10增加到20
connection-timeout: 10000 # 从30秒降低到10秒
idle-timeout: 300000 # 从10分钟降低到5分钟
leak-detection-threshold: 30000 # 从60秒降低到30秒
validation-timeout: 3000 # 从5秒降低到3秒
MySQL 会话参数优化:
innodb_lock_wait_timeout=10 # 从30秒降低到10秒
wait_timeout=300 # 新增,5分钟
interactive_timeout=300 # 新增,5分钟
效果:
- 支持更多并发数据库操作
- 更快检测和释放死锁
- 更快发现连接泄漏问题
- 减少数据库连接等待时间
3. ✅ HTTP 客户端连接池配置(高优先级)
文件: src/main/java/com/gameplatform/server/service/external/ScriptClient.java
新增配置:
// 连接池配置
ConnectionProvider connectionProvider = ConnectionProvider.builder("script-client-pool")
.maxConnections(100) // 最大连接数
.pendingAcquireMaxCount(200) // 等待队列大小
.pendingAcquireTimeout(Duration.ofSeconds(10))
.maxIdleTime(Duration.ofSeconds(30))
.maxLifeTime(Duration.ofMinutes(5))
.evictInBackground(Duration.ofSeconds(60))
.build();
// HttpClient 配置
HttpClient httpClient = HttpClient.create(connectionProvider)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeoutMs)
.responseTimeout(Duration.ofMillis(readTimeoutMs))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(...))
.addHandlerLast(new WriteTimeoutHandler(...)))
.compress(true);
效果:
- 避免 HTTP 连接耗尽
- 支持连接复用,提升性能
- 自动清理过期连接
- 启用 HTTP 压缩减少带宽
4. ✅ 异步线程池优化(中优先级)
文件: src/main/java/com/gameplatform/server/config/AsyncConfig.java
设备检测线程池优化:
deviceDetectionExecutor:
corePoolSize: 10 # 从3增加到10
maxPoolSize: 50 # 从10增加到50
queueCapacity: 500 # 从100增加到500
rejectedPolicy: DiscardOldest # 改为丢弃最旧,避免阻塞HTTP线程
新增通用异步线程池:
taskExecutor:
corePoolSize: 20
maxPoolSize: 100
queueCapacity: 1000
rejectedPolicy: CallerRunsPolicy
效果:
- 支持更多并发异步任务
- 避免 HTTP 线程被阻塞
- 提供更好的任务隔离
5. ✅ 事务超时优化(中优先级)
文件: src/main/resources/application.yml
优化项:
spring:
transaction:
default-timeout: 15 # 从30秒降低到15秒
mvc:
async:
request-timeout: 60000 # 新增,异步请求超时60秒
效果:
- 更快检测和终止长事务
- 减少数据库连接占用时间
- 避免死锁长时间等待
6. ✅ 监控端点扩展
文件: src/main/resources/application.yml
新增监控端点:
management:
endpoints:
web:
exposure:
include: health,info,metrics,threaddump
效果:
- 可以查看线程状态 (
/actuator/threaddump) - 可以查看性能指标 (
/actuator/metrics) - 便于排查性能问题
性能提升预期
并发能力对比
| 配置项 | 优化前 | 优化后 | 提升幅度 |
|---|---|---|---|
| Tomcat 最大线程数 | 200(默认) | 200 | - |
| Tomcat 最小线程数 | 10(默认) | 20 | +100% |
| Tomcat 最大连接数 | 8192(默认) | 10000 | +22% |
| 数据库连接池 | 50 | 100 | +100% |
| HTTP 客户端连接池 | 无限制(默认) | 100(受控) | 稳定性提升 |
| 设备检测线程池 | 3-10 | 10-50 | +400% |
| 异步任务线程池 | 无 | 20-100 | 新增 |
响应时间改善
- 数据库操作: 连接获取时间从可能的30秒降低到10秒以内
- HTTP 请求: 连接复用,减少建立连接开销
- 锁等待: 从30秒降低到10秒,更快释放资源
- 连接泄漏检测: 从60秒降低到30秒,更快发现问题
验证步骤
1. 启动应用检查日志
启动后应该看到类似日志:
ScriptClient 初始化完成: baseUrl=..., 最大连接数=100
设备检测线程池已初始化: coreSize=10, maxSize=50, queueCapacity=500
通用异步任务线程池已初始化: coreSize=20, maxSize=100, queueCapacity=1000
HikariPool-1 - Starting...
HikariPool-1 - Start completed.
2. 检查监控端点
# 查看健康状态
curl http://localhost:18080/actuator/health
# 查看线程信息
curl http://localhost:18080/actuator/threaddump
# 查看指标
curl http://localhost:18080/actuator/metrics
curl http://localhost:18080/actuator/metrics/hikaricp.connections.active
curl http://localhost:18080/actuator/metrics/tomcat.threads.busy
3. 并发压力测试
使用工具如 JMeter 或 Apache Bench 进行压力测试:
# 使用 Apache Bench 测试
ab -n 10000 -c 200 http://localhost:18080/api/some-endpoint
# 使用 wrk 测试
wrk -t12 -c400 -d30s http://localhost:18080/api/some-endpoint
4. 监控关键指标
在压力测试期间,监控以下指标:
- Tomcat 线程池使用率
- HikariCP 连接池使用率
- HTTP 客户端连接数
- 异步线程池队列长度
- 响应时间分布
- 错误率
性能调优建议
根据实际负载调整
-
如果发现 Tomcat 线程不够:
server: tomcat: threads: max: 300 # 可以继续增加 -
如果数据库连接池经常满:
hikari: maximum-pool-size: 150 # 可以继续增加 -
如果异步任务队列经常满:
executor.setQueueCapacity(1000); // 增加队列 executor.setMaxPoolSize(100); // 增加最大线程
JVM 参数建议
如果并发量很大,建议调整 JVM 参数:
java -jar app.jar \
-Xms2g \ # 初始堆内存
-Xmx4g \ # 最大堆内存
-XX:+UseG1GC \ # 使用G1垃圾收集器
-XX:MaxGCPauseMillis=200 \ # GC暂停目标
-XX:ParallelGCThreads=8 \ # 并行GC线程数
-XX:ConcGCThreads=2 # 并发GC线程数
常见问题排查
1. 连接池耗尽
症状: 日志出现 "Connection is not available"
排查:
curl http://localhost:18080/actuator/metrics/hikaricp.connections.active
curl http://localhost:18080/actuator/metrics/hikaricp.connections.pending
解决: 增加 maximum-pool-size 或检查是否有连接泄漏
2. 线程池满
症状: 日志出现 "Task rejected" 或请求响应变慢
排查:
curl http://localhost:18080/actuator/metrics/tomcat.threads.busy
curl http://localhost:18080/actuator/threaddump
解决: 增加线程池大小或优化慢接口
3. HTTP 连接超时
症状: 日志出现 "Connection timeout"
排查: 检查外部服务是否正常,网络是否畅通
解决:
- 调整超时时间
- 增加重试机制
- 添加断路器
后续优化建议
- 添加缓存: 使用 Redis 缓存热点数据
- 读写分离: 使用数据库主从复制
- 服务拆分: 将耗时操作拆分到独立服务
- 消息队列: 异步处理非实时任务
- CDN: 静态资源使用 CDN 加速
回滚方案
如果优化后出现问题,可以通过以下步骤回滚:
# 恢复配置文件
git checkout HEAD~1 -- src/main/resources/application.yml
git checkout HEAD~1 -- src/main/java/com/gameplatform/server/service/external/ScriptClient.java
git checkout HEAD~1 -- src/main/java/com/gameplatform/server/config/AsyncConfig.java
# 重新编译部署
mvn clean package -DskipTests
总结
本次优化从以下几个维度提升了系统并发能力:
- ✅ HTTP 服务器: Tomcat 线程池和连接池优化
- ✅ 数据库: HikariCP 连接池优化,锁等待超时优化
- ✅ HTTP 客户端: Reactor Netty 连接池配置
- ✅ 异步处理: 线程池扩容和策略优化
- ✅ 事务管理: 超时时间优化
- ✅ 监控: 扩展监控端点
预期可以将系统并发处理能力提升 2-5 倍,响应时间降低 30-50%。
建议在生产环境部署前,先在测试环境进行充分的压力测试验证。