在 2GB 内存的云服务器上运行 Tomcat + MySQL,必须严格控制两者内存占用,避免触发 OOM(Out Of Memory)。以下是经过验证的优化方案:
一、MySQL 优化(建议占用 ≤512MB)
1. 关键参数配置(my.cnf)
[mysqld]
# 基础设置
max_connections = 50 # 限制并发连接数
thread_cache_size = 8 # 线程缓存
table_open_cache = 200 # 表缓存
sort_buffer_size = 64K # 排序缓冲区(默认 2M 太大)
read_buffer_size = 64K # 读缓冲区
read_rnd_buffer_size = 64K # 随机读缓冲区
join_buffer_size = 64K # 连接缓冲区
# 内存核心参数
innodb_buffer_pool_size = 256M # 占物理内存 12-15%
innodb_log_file_size = 32M # 日志文件大小
innodb_flush_method = O_DIRECT # 绕过系统缓存
query_cache_size = 0 # 查询缓存已废弃,设为 0
tmp_table_size = 64M # 临时表大小
max_heap_table_size = 64M
# 其他优化
skip-name-resolve = 1 # 跳过 DNS 解析
local-infile = 0 # 禁用本地导入
log_bin = /var/log/mysql/bin.log # 开启二进制日志(可选)
2. 启动前检查
# 查看当前 MySQL 内存估算
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
free -h # 确认剩余内存 > 500MB
二、Tomcat 优化(建议占用 ≤896MB)
1. JVM 参数配置(catalina.sh)
export CATALINA_OPTS="-Xms256m -Xmx512m
-XX:MaxMetaspaceSize=128m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/tomcat/heapdump.hprof
-Djava.awt.headless=true
-Dfile.encoding=UTF-8"
2. 关键说明
-Xms和-Xmx设为相同值(避免动态扩容开销)- G1 GC 适合中小堆内存
- Metaspace 限制防止类加载泄漏
- 启用堆转储便于问题排查
三、系统级优化
1. 调整内核参数
# /etc/sysctl.conf
vm.swappiness = 10 # 降低交换使用倾向
vm.overcommit_memory = 1 # 允许过度分配内存
vm.vfs_cache_pressure = 50 # 减少 inode/dentry 回收压力
sysctl -p
2. 限制其他服务
# 关闭不必要的服务
systemctl disable nginx apache2 postfix
# 监控工具轻量替代
# 用 htop 替代 top,用 iotop 替代 atop
四、应用层优化
1. Tomcat 连接器优化
<!-- server.xml -->
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="50"
minSpareThreads="5"
acceptCount="100"
URIEncoding="UTF-8" />
2. 数据库连接池
# HikariCP 配置(推荐)
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
五、监控与调优策略
1. 实时监控脚本
#!/bin/bash
while true; do
echo "=== $(date) ==="
free -h
mysqladmin status | grep Threads_running
jstat -gcutil $(pgrep java | head -1) 1000 2>/dev/null || echo "No Java process"
sleep 30
done
2. 告警阈值
- MySQL 缓冲池使用率 > 80% → 预警
- Tomcat GC 停顿时间 > 500ms → 预警
- 系统 Swap 使用 > 10% → 紧急处理
六、应急措施
当出现 OOM 时:
- 立即降级:临时增加
max_connections和maxThreads - 分析堆转储:
jmap -dump:format=b,file=heap.hprof <pid> - 重启顺序:先重启 MySQL,再重启 Tomcat
- 长期方案:考虑升级到 4GB 实例或拆分服务
重要提示:生产环境建议先在测试环境完整验证配置,并持续监控实际负载情况。2GB 内存仅适合低流量场景(QPS < 100),高并发场景需考虑架构升级。
云计算导航