在 2 核 2G(双核 CPU,2GB 内存)的服务器上同时运行 Tomcat 和 MySQL,资源非常紧张。这种配置下,核心策略是“极致压缩内存占用”和“限制并发”,否则极易触发 Linux 的 OOM Killer(内存溢出杀手),导致服务频繁崩溃。
以下是针对该硬件配置的详细优化方案:
1. 操作系统层面优化(基础)
在调整应用之前,必须先确保系统本身不浪费资源。
- 关闭 Swap(交换分区):
- 原因:2G 内存非常宝贵,一旦开启 Swap,MySQL 或 Tomcat 发生轻微内存波动就会触发磁盘交换,导致服务器瞬间卡死(I/O 等待飙升)。
- 操作:临时关闭
sudo swapoff -a;永久关闭需修改/etc/fstab注释掉 swap 行。
- 清理后台服务:
- 禁用不必要的 systemd 服务(如 NetworkManager, Bluetooth, Avahi 等),只保留网络、SSH 和必要的日志轮转服务。
- 文件系统挂载参数:
- 如果是 CentOS/Ubuntu,建议将
/tmp挂载为tmpfs(内存盘),减少磁盘 I/O。 - 数据库目录挂载参数可考虑添加
noatime以减少元数据写入开销。
- 如果是 CentOS/Ubuntu,建议将
2. MySQL 优化(重中之重)
MySQL 是内存大户,必须严格限制其最大内存使用量,预留至少 500MB 给 Tomcat 和系统内核。
A. 关键配置文件 (my.cnf) 调整
建议将 innodb_buffer_pool_size 设置为物理内存的 30%~40%(约 600MB-800MB),这是最核心的优化点。
[mysqld]
# 基础设置
port = 3306
basedir = /usr/local/mysql
datadir = /var/lib/mysql
socket = /tmp/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid
user = mysql
# --- 内存核心配置 (关键) ---
# 限制 InnoDB 缓冲池大小,防止吃光内存
innodb_buffer_pool_size = 600M
# 如果主要是小表查询,可适当调低;如果是大表,尽量接近 700M
innodb_log_file_size = 256M
# --- 连接与线程 ---
# 限制最大连接数,2G 机器不建议超过 50
max_connections = 50
thread_cache_size = 10
skip-name-resolve # 禁用 DNS 解析,提升连接速度并减少网络请求
# --- 日志与性能 ---
# 关闭慢查询日志(生产环境建议开启但限制时间,测试环境可关闭以省 IO)
slow_query_log = 0
long_query_time = 10
# 安全设置
local_infile = 0
symbolic-links = 0
B. 启动参数检查
确保启动脚本中没有额外的 -Xmx 或 -Xms 类似参数(那是 Java 的),MySQL 主要靠 my.cnf 控制。
3. Tomcat 优化
Tomcat 需要足够的堆内存来运行 JVM,同时不能影响 MySQL。建议预留 400MB~500MB 给 Tomcat。
A. JVM 内存参数 (setenv.sh 或 catalina.sh)
不要直接使用默认值,强制指定最小和最大堆内存,避免动态扩容带来的抖动。
# 编辑 $CATALINA_BASE/bin/setenv.sh (如果没有则新建)
export CATALINA_OPTS="-Xms400m -Xmx500m"
# 可选:开启 G1 垃圾回收器,对低内存更友好
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
# 可选:开启 JIT 编译优化
export CATALINA_OPTS="$CATALINA_OPTS -XX:+AggressiveOpts -XX:+UseStringDeduplication"
注意:-Xmx500m 表示最大堆 500MB,加上非堆内存(Metaspace, Thread Stack 等),总占用约为 600-700MB。
B. Tomcat 自身配置 (server.xml)
- Connector 线程数:默认通常较大,需减小。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads="100" <!-- 降低并发上限 --> minSpareThreads="10" acceptCount="50" <!-- 排队队列长度 --> /> - APR/NIO:确保使用 NIO 模式(Tomcat 8+ 默认),避免使用 BIO。
4. 中间件与架构层面的妥协
由于硬件限制,软件架构上必须做减法:
- 关闭不必要的功能:
- 如果不需要,关闭 Tomcat 的 AJP 协议(只保留 HTTP)。
- 关闭 MySQL 的 Query Cache(MySQL 5.7+ 已废弃,8.0 中移除,无需担心)。
- 应用层优化:
- JDBC 连接池:将 Druid 或 HikariCP 的最大连接数限制在 10-20 之间,不要设置过大。
- 静态资源:如果可能,将图片、CSS、JS 等静态资源托管到对象存储(如阿里云 OSS)或 CDN,减轻服务器带宽和 CPU 压力。
- 监控与报警:
- 部署轻量级监控(如 Prometheus + Node Exporter,或者简单的 Shell 脚本),监控
free -h和dmesg | grep -i kill。 - 一旦内存使用率超过 90%,立即收到告警。
- 部署轻量级监控(如 Prometheus + Node Exporter,或者简单的 Shell 脚本),监控
5. 预期效果与风险提示
| 指标 | 优化前风险 | 优化后预期 |
|---|---|---|
| 内存使用 | 容易爆满,触发 OOM | 稳定在 1.6GB 左右,留有余地 |
| 并发能力 | 高并发下直接假死 | 支持中小流量(QPS 100-300 级别) |
| 稳定性 | 随机崩溃 | 长时间运行稳定,无频繁重启 |
重要提示:
2 核 2G 属于入门级/测试级配置。
- 如果是个人博客、内部管理系统、低频 API,上述配置可以跑通。
- 如果是电商、高并发业务、复杂报表,此配置存在极大风险。即使优化到极致,遇到突发流量依然会挂。
- 终极建议:如果预算允许,优先升级内存至 4G,成本增加不多,但稳定性和承载能力会有质的飞跃。如果无法升级,务必做好限流(Nginx 限流)和降级预案。
云小栈