server:
tomcat:
#线程池配置
max-threads: 200 # 最大工作线程数(建议:2~4倍CPU核心数,如16核设200-400)
min-spare-threads: 20 # 最小空闲线程(应对突发流量,建议:max-threads的10%~20%)
# 连接控制
max-connections: 10000 # 最大连接数(需结合系统句柄数ulimit -n设置,建议:系统句柄数的70% / 应用数)
accept-count: 500 # 等待队列长度(建议:max-threads的1~2倍)
connection-timeout: 5000 # 连接超时(毫秒,建议:3~5秒)
# 高级参数
max-swallow-size: -1 # 处理中断请求的剩余数据(-1表示无限制,大文件上传场景建议设置)
keep-alive:
timeout: 15000 # KeepAlive超时时间(建议:10~15秒)
在 Spring Boot 中,server.tomcat.max-connections
是 Tomcat 服务器的关键配置参数,用于控制并发连接数上限。它与系统文件句柄数(File Descriptor Limit)直接相关,若配置不当可能导致 Too many open files
错误。以下是详细解释和配置建议:
server.tomcat.max-connections
的作用10000
(但实际受系统文件句柄数限制)。cat /proc/sys/fs/file-max
(通常数万到百万)。ulimit -n
(默认通常为 1024
)。max-connections=10000
,但系统文件句柄数仅为 4096
,当并发连接超过 4096 时,会触发 java.net.SocketException: Too many open files
错误。临时生效(重启失效):
ulimit -n 65535 # 设置当前会话的文件句柄数为 65535
永久生效:
修改 /etc/security/limits.conf
,添加以下内容:
* soft nofile 65535 # 所有用户软限制
* hard nofile 65535 # 所有用户硬限制
max-connections
server:
tomcat:
max-connections: 10000 # 建议不超过系统文件句柄数的 70%(如 65535 * 0.7 ≈ 45000)
# 其他参数
max-threads: 200 # 工作线程数(处理请求的核心并发能力)
accept-count: 100 # 等待队列长度(超出后拒绝连接)
max-connections ≤ (系统文件句柄数 - 其他应用占用) * 安全系数
65535
,假设其他应用占用 5000
,安全系数为 0.8
。max-connections ≤ (65535 - 5000) * 0.8 ≈ 48428
,可配置 40000
。# 查看系统全局已用句柄数
cat /proc/sys/fs/file-nr
# 查看 Tomcat 进程占用的句柄数
lsof -p | wc -l
通过 Spring Boot Actuator 的 metrics
端点:
curl http://localhost:8080/actuator/metrics/tomcat.connections.max
输出示例:
{
"name": "tomcat.connections.max",
"measurements": [{"statistic": "VALUE", "value": 10000}]
}
若出现 Too many open files
错误:
ulimit -n
和 /proc/sys/fs/file-max
。netstat -an | grep ESTABLISHED | wc -l
。参数 | 说明 |
---|---|
server.tomcat.max-threads |
Tomcat 工作线程池大小(决定并发请求处理能力)。 |
server.tomcat.accept-count |
等待队列长度,当所有线程繁忙时,新连接进入队列,超出后拒绝连接。 |
server.connection-timeout |
连接超时时间(毫秒),超时后关闭空闲连接。 |
max-connections
必须小于系统文件句柄数,否则会导致连接拒绝或崩溃。65535
(通过 limits.conf
设置)。max-connections
:根据业务并发量设定(如 10000~40000
)。max-threads
和 accept-count
,确保线程池和队列能应对突发流量。针对 Druid 连接池的性能优化,需从 连接池配置、监控集成、SQL 优化、防御性设计 四个方向入手。以下是详细的优化策略和配置示例:
在 application.yml
中配置合理参数(假设 DRDS 最大连接数为 300,3 个应用共存):
spring:
datasource:
druid:
# 核心连接池参数
initial-size: 5 # 初始连接数(避免冷启动延迟)
min-idle: 5 # 最小空闲连接(维持基本可用性)
max-active: 30 # 最大活跃连接数(按 DRDS 总配额分配)
max-wait: 2000 # 获取连接最大等待时间(毫秒,避免线程阻塞)
# 连接有效性检查
validation-query: SELECT 1 # 心跳检测 SQL(简单查询)
test-on-borrow: true # 借用连接时校验(确保连接有效)
test-while-idle: true # 空闲时定期校验(默认 true)
time-between-eviction-runs-millis: 60000 # 空闲连接检查间隔(60秒)
min-evictable-idle-time-millis: 300000 # 连接最小空闲时间(5分钟)
spring:
datasource:
druid:
remove-abandoned: true # 启用泄漏连接回收
remove-abandoned-timeout: 300 # 连接被占用超过 300 秒视为泄漏
log-abandoned: true # 记录泄漏连接的堆栈信息(便于排查)
spring:
datasource:
druid:
# 监控统计
stat-view-servlet:
enabled: true # 启用监控页面
url-pattern: /druid/* # 监控访问路径
login-username: admin # 监控账号(生产环境必设)
login-password: druid@123
web-stat-filter:
enabled: true # 启用 Web 请求统计
url-pattern: /* # 统计所有 URL
exclusions: "*.js,*.css,/druid/*" # 排除静态资源
filter:
stat:
enabled: true # 启用 SQL 统计
slow-sql-millis: 1000 # 定义慢 SQL 阈值(1秒)
log-slow-sql: true # 记录慢 SQL 日志
http://your-server:8080/druid
,输入账号密码后可查看:
spring:
datasource:
druid:
filters: stat,wall,slf4j # 启用统计、防火墙、日志过滤器
wall:
enabled: true
config:
delete-allow: false # 禁止 DELETE 无 WHERE 语句
drop-table-allow: false # 禁止 DROP TABLE
multi-statement-allow: false # 禁止批量执行 SQL
spring:
datasource:
druid:
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的预编译语句数
pool-prepared-statements: true # 启用预编译语句池
spring:
datasource:
druid:
async-init: true # 异步初始化连接池(避免应用启动阻塞)
spring:
datasource:
druid:
# 连接存活策略
keep-alive: true # 启用保活机制(默认 false)
phy-timeout-millis: 600000 # 物理连接最大存活时间(10分钟)
# 连接有效性检查优化
validation-query-timeout: 3000 # 心跳检测超时时间(3秒)
通过 druid-spring-boot-starter
将监控数据暴露给 Spring Boot Actuator:
management:
endpoints:
web:
exposure:
include: health,druid
在 druid
过滤器中添加 Trace ID 传递:
@Bean
public FilterRegistrationBean<Filter> druidFilter() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new WebStatFilter());
registration.addInitParameter("exclusions", "*.js,*.css,/druid/*");
registration.addInitParameter("profileEnable", "true");
registration.addUrlPatterns("/*");
return registration;
}
SQL 监控
和 慢 SQL 日志
,优化索引和查询逻辑。remove-abandoned
并分析日志中的泄漏堆栈。max-active
和 max-wait
。mysql-connector-java:8.0.33
),修复已知性能问题。spring:
datasource:
druid:
url: jdbc:mysql://drds-proxy:3306/db?useSSL=false
username: user
password: pass
initial-size: 5
min-idle: 5
max-active: 30
max-wait: 2000
validation-query: SELECT 1
test-on-borrow: true
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
filters: stat,wall,slf4j
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: druid@123
web-stat-filter:
enabled: true
url-pattern: /*
wall:
config:
delete-allow: false
async-init: true
keep-alive: true
phy-timeout-millis: 600000
通过上述优化,Druid 连接池可实现:
最终需结合压测工具(如 JMeter)验证配置效果,并根据实际业务负载动态调整参数。
在 16核64G 内存 的服务器上运行 5个 Java 程序(其中两个是核心主应用),需为这两个主应用分配更多资源,同时预留足够内存和 CPU 给其他程序和系统。以下是针对两个主应用的 JVM 参数配置方案及详细说明:
java -Xms24G -Xmx24G \ # 堆内存 24GB(占 64G 的 37.5%)
-XX:MaxMetaspaceSize=1G \ # 元空间上限 1GB(防类加载泄露)
-XX:MaxDirectMemorySize=4G \ # 堆外内存上限(Netty/NIO 场景需要)
-XX:+UseG1GC \ # 启用 G1 垃圾收集器(平衡吞吐和延迟)
-XX:MaxGCPauseMillis=200 \ # 目标最大 GC 停顿时间 200ms
-XX:ParallelGCThreads=8 \ # 并行 GC 线程数(16核 * 0.5 = 8)
-XX:ConcGCThreads=4 \ # 并发 GC 线程数(ParallelGCThreads * 0.5)
-XX:InitiatingHeapOccupancyPercent=45 \ # 堆占用 45% 触发并发标记
-XX:+ExplicitGCInvokesConcurrent \ # System.gc() 触发并发 GC
-XX:+PrintGCDetails \ # 打印 GC 日志(生产环境可关闭)
-XX:+PrintGCDateStamps \
-Xloggc:/opt/app1_gc.log \
-jar app1.jar
java -Xms20G -Xmx20G \ # 堆内存 20GB(占 64G 的 31.25%)
-XX:MaxMetaspaceSize=1G \
-XX:MaxDirectMemorySize=2G \
-XX:+UseZGC \ # 启用 ZGC(亚毫秒级停顿,JDK 17+)
-XX:ConcGCThreads=8 \ # ZGC 并发线程数(16核 * 0.5 = 8)
-XX:SoftMaxHeapSize=18G \ # 弹性堆内存上限(ZGC 特性)
-XX:+UnlockExperimentalVMOptions \ # 启用实验性参数(JDK 17 需要)
-XX:+ZGenerational \ # 启用分代 ZGC(JDK 21+)
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-Xloggc:/opt/app2_gc.log \
-jar app2.jar
资源 | 应用1 | 应用2 | 其他3个程序 | 系统预留 | 总计 |
---|---|---|---|---|---|
堆内存 | 24G | 20G | ~10G | 10G | 64G |
元空间 | 1G | 1G | ~1G | - | 3G |
堆外内存 | 4G | 2G | ~2G | - | 8G |
24+20+10 +1+1+2 +10= 68G
(略超 64G,需根据实际调整,优先保障主应用)。ParallelGCThreads=8
:16 核下分配 50% 给并行 GC,避免 GC 线程抢占业务线程。ConcGCThreads=4
:并发标记阶段线程数,减少对业务影响。SoftMaxHeapSize
:允许堆弹性伸缩,应对突发负载。MaxMetaspaceSize
:限制元空间,防止第三方库(如反射、动态代理)导致内存泄漏。MaxDirectMemorySize
:控制堆外内存(如 Netty 的 DirectByteBuffer),避免 Native 内存溢出。ExplicitGCInvokesConcurrent
:防止代码调用 System.gc()
触发 Full GC。# 将应用1绑定到 CPU 0-7,应用2绑定到 CPU 8-15(需 root 权限)
taskset -c 0-7 java -Xms24G ... app1.jar
taskset -c 8-15 java -Xms20G ... app2.jar
# 配置大页(需系统支持)
-XX:+UseLargePages -XX:LargePageSizeInBytes=2M
# 修改 /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
# 修改 /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
指标 | 工具 | 健康阈值 |
---|---|---|
JVM Heap Used | VisualVM/Prometheus | < 80% Xmx |
GC Pause Time | GC 日志 | < 200ms(G1)、< 10ms(ZGC) |
CPU Usage | top/htop | < 70%(单核) |
Direct Memory | NMT(Native Memory Tracking) | < MaxDirectMemorySize |
IHOP
或 MaxGCPauseMillis
。jcmd VM.native_memory
查看 Native 内存分布。Xmx
或优化代码逻辑(如缓存策略、对象池)。通过上述配置,可在 16核64G 服务器上实现多应用共存下的资源平衡与性能优化。