Ubuntu 上 Tomcat 的 JVM 优化实操指南
一 基线评估与监控
- 建立可复现负载:用 Apache JMeter 创建测试计划,记录吞吐、P95/P99 时延、错误率,形成优化前后对比基线。
- 系统资源观测:用 top/htop、free -m、df -h、iftop 排查 CPU、内存、磁盘、网络瓶颈。
- JVM 与应用观测:用 JConsole/VisualVM 观察堆、线程、类加载与 GC 行为;发生 OOM 时结合 Heap Dump + Eclipse MAT 定位泄漏对象与引用链。
- 日志驱动调优:分析 catalina.out、localhost_access_log 的错误码分布、慢请求与异常堆栈,联动参数迭代。
二 JVM 参数优化
- 堆与元空间
- 将 -Xms 与 -Xmx 设为相同值(如各为物理内存的1/2,视负载与容器而定),避免运行期扩缩堆带来的抖动。
- 设置 -XX:MaxMetaspaceSize=… 防止元空间无限增长(Java 8+)。
- 垃圾回收器
- 大堆与多核场景优先 G1GC(-XX:+UseG1GC),可配合 -XX:MaxGCPauseMillis=200 平衡吞吐与停顿。
- 诊断与排障
- 开启 GC 日志:如 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/opt/tomcat/logs/gc.log。
- OOM 自动转储:如 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tomcat/logs/heap.hprof。
- 熵源与启动阻塞
- 在 $JAVA_HOME/jre/lib/security/java.security 将 securerandom.source 调整为 /dev/./urandom,或在 Ubuntu 安装并启用 rng-tools,缓解启动或首次请求因熵不足导致的长时间阻塞。
- 放置位置
- 在 /etc/default/tomcat9(或 catalina.sh) 的 JAVA_OPTS/CATALINA_OPTS 中配置,注意服务方式下以 systemd 的环境变量为准。
三 Tomcat 连接器与线程联动
- 协议与 I/O:优先 NIO/NIO2 或 HTTP/2 提升并发与吞吐。
- 线程池关键参数(按压测结果微调):
- maxThreads(并发处理线程上限,如 200)
- minSpareThreads(常驻最小空闲线程,如 25)
- acceptCount(队列长度,如 100)
- 其他:connectionTimeout、URIEncoding=“UTF-8”、enableLookups=“false”
- 压缩与复用
- 启用 GZIP 压缩(如 compression=“on”、compressionMinSize=“2048”)
- 合理设置 maxKeepAliveRequests 平衡连接复用与资源占用。
- 线程与内存联动
- 线程数 × 每线程栈(默认约 1MB,可用 -Xss 微调)会占用额外本地内存;并发高时优先增加 maxThreads 与优化 GC,谨慎增大堆以免加剧 GC 压力。
四 系统与运行环境优化
- 文件描述符与进程数
- 在 /etc/security/limits.conf 增加如 * soft nofile 65535、* hard nofile 65535,并在 systemd 服务单元中设置 LimitNOFILE=65535,避免 “Too many open files”。
- 内核网络参数(/etc/sysctl.conf 或 sysctl -w)
- 如 net.core.somaxconn=4096、net.ipv4.tcp_max_syn_backlog=4096、net.ipv4.tcp_tw_reuse=1、net.ipv4.tcp_fin_timeout=60,提升高并发连接处理能力并降低握手与回收时延。
- 服务治理
- 以 systemd 方式运行,配置 自动重启、内存/CPU 限制、最小权限专用用户,分离日志与二进制目录,便于审计与回滚。
五 快速检查清单与示例配置
- 快速检查清单
- 服务与资源:systemd 重启策略生效、ulimit -n ≥ 65535、内核网络参数已加载。
- JVM:-Xms == -Xmx、启用 G1GC、开启 GC 日志与 OOM 堆转储、设置 MaxMetaspaceSize。
- 连接器:NIO/NIO2 或 HTTP/2、maxThreads/acceptCount 与业务并发匹配、enableLookups=false、启用 GZIP、合理 connectionTimeout。
- 日志:AccessLogValve 轮转与保留、logging.properties 级别与异步、logrotate 策略与通知、集中化观测与告警。
- 应用:连接池与超时、异步化长任务、静态资源剥离、SQL 与索引优化、灰度与回滚预案。
- 示例配置片段
- server.xml(连接器要点)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200" minSpareThreads="25" acceptCount="100"
maxKeepAliveRequests="100"
enableLookups="false"
compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,application/json"
URIEncoding="UTF-8" />
- logging.properties(异步与级别)
handlers = 1catalina.org.apache.juli.AsyncFileHandler, \
2localhost.org.apache.juli.AsyncFileHandler, \
java.util.logging.ConsoleHandler
.level = INFO
org.apache.catalina.level = WARNING
java.util.logging.ConsoleHandler.level = WARNING
- JVM_OPTS(示例,放在 /etc/default/tomcat9 或 catalina.sh)
export JAVA_OPTS=" \
-server \
-Xms2g -Xmx2g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:MaxMetaspaceSize=512m \
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/opt/tomcat/logs/gc.log \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tomcat/logs/heap.hprof \
-Djava.security.egd=file:/dev/./urandom"
- logrotate(/etc/logrotate.d/tomcat,按日轮转与压缩)
/opt/tomcat/logs/catalina.out {
daily
rotate 7
compress
missingok
notifempty
create 640 tomcat tomcat
postrotate
/bin/kill -USR1 $(cat /opt/tomcat/temp/tomcat.pid 2>/dev/null) 2>/dev/null || true
endscript
}
- 提示:以上为通用起点,需结合 压测与监控 逐步微调;堆与线程并非越大越好,避免 长时间 GC 停顿 与 线程创建失败。