在 2 核 2G(约 1.5GB-1.8GB 可用内存)的服务器上部署 Spring Boot,核心挑战在于内存管理。Spring Boot 默认会尝试占用较多堆内存(通常最大可设为物理内存的 1/4),极易触发 OOM(Out Of Memory)导致进程被系统杀死。
以下是针对 CentOS 或 Ubuntu 的系统级与 JVM 级的优化配置指南:
一、JVM 参数调优(最关键)
Spring Boot 启动时会自动计算堆内存大小。在低配服务器上,必须手动覆盖默认值,防止内存溢出。
1. 推荐 JVM 参数组合
假设服务器可用物理内存为 1.8GB,建议配置如下:
# 设置最大堆内存 (Xmx):建议设为总内存的 60%-70%,预留空间给操作系统和 Native 内存
-Xmx512m
# 设置初始堆内存 (Xms):与 Xmx 保持一致,避免运行时频繁扩容收缩带来的性能抖动
-Xms512m
# 元空间 (Metaspace):存放类定义信息,Spring Boot 启动时会加载大量类
-XX:MaxMetaspaceSize=128m
# 垃圾回收器:G1 GC 在中小内存下表现较好,或者使用 Serial GC 以节省 CPU 开销
# 方案 A (推荐): G1 GC
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
# 方案 B (极简/CPU 极紧): Serial GC (适合纯 IO 或逻辑简单应用)
# -XX:+UseSerialGC
# 关闭自动调整堆大小 (防止 Spring Boot 试图占用更多内存)
-XX:+UseContainerSupport=false
# 注意:如果使用了 Docker,通常需要开启 UseContainerSupport=true 并配合 -Xmx,但在宿主机直接运行建议设为 false 或手动指定
启动命令示例:
java -jar -Xms512m -Xmx512m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 your-app.jar
2. Spring Boot 配置文件 (application.yml / application.properties)
如果你是通过环境变量启动,也可以在配置文件中指定:
spring:
jvm:
# 某些版本支持通过属性设置,但通常建议在启动脚本中强制指定
options: "-Xms512m -Xmx512m"
注:最稳妥的方式是在 systemd 服务文件或 Docker 启动命令中直接传入 JVM 参数。
二、操作系统级优化
1. 增加 Swap 分区(虚拟内存)
2G 物理内存非常紧张,一旦应用出现内存泄漏或突发流量,Swap 是最后的防线。虽然 Swap 会降低性能,但能防止服务直接崩溃。
Ubuntu/CentOS 通用创建步骤:
# 1. 检查是否已有 swap
free -h
# 2. 创建 2G 的 swap 文件 (如果物理内存只有 2G,建议 swap 设为 2G-4G)
sudo fallocate -l 4G /swapfile
# 如果 fallocate 失败,可用 dd 命令:sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
# 3. 设置权限
sudo chmod 600 /swapfile
# 4. 格式化为 swap
sudo mkswap /swapfile
# 5. 启用
sudo swapon /swapfile
# 6. 验证
swapon --show
# 7. 永久生效 (写入 fstab)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 8. 调整 Swappiness (降低交换频率,优先使用物理内存)
# 默认通常是 60,建议调整为 10
sudo sysctl vm.swappiness=10
# 临时生效:sudo sysctl vm.swappiness=10
# 永久生效:echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
2. 调整内核参数
优化 TCP 连接处理和高并发下的资源限制。
# 编辑 sysctl.conf
sudo vim /etc/sysctl.conf
# 添加或修改以下参数:
# 允许更多的文件句柄
fs.file-max = 65535
# 增加 TCP 端口范围
net.ipv4.ip_local_port_range = 1024 65535
# 提高 TCP 连接队列长度,防止连接拒绝
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 4096
# 优化 TCP 重传机制
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0 # 新版内核建议关闭 tw_recycle 以防 NAT 问题
# 应用配置
sudo sysctl -p
3. 文件描述符限制
Spring Boot 应用在高并发下容易达到 ulimit 限制。
# 临时生效
ulimit -n 65535
# 永久生效:编辑 /etc/security/limits.conf
# 添加以下内容:
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
三、应用架构与代码层面的优化
除了硬件和 OS 配置,代码层面的优化同样重要:
-
禁用不必要的功能:
- 如果不需要 Actuator 监控,移除相关依赖。
- 如果不需要 Swagger,移除
springfox等文档生成器。 - 关闭不用的 Starter(如
spring-boot-starter-data-jpa若只用 MyBatis 则不要引入)。
-
数据库连接池调优:
在 2G 内存下,HikariCP 的连接数不宜过大。spring: datasource: hikari: maximum-pool-size: 10 # 默认可能是 10-20,视业务量调整,保守起见设小一点 minimum-idle: 2 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 -
缓存策略:
- 尽量使用 Redis 做分布式缓存,减少本地堆内存压力。
- 如果必须用本地缓存(Caffeine/Guava),务必设置严格的
expireAfterWrite和maximumSize。
-
日志级别:
- 生产环境将日志级别设为
INFO或WARN,避免 DEBUG 级别产生大量日志占用磁盘 I/O 和内存缓冲。logging: level: root: INFO com.yourpackage: INFO org.springframework.web: WARN
- 生产环境将日志级别设为
四、部署方式建议
1. Systemd 服务管理 (推荐)
使用 systemd 可以方便地管理重启、看门狗和自动恢复。
创建 /etc/systemd/system/myapp.service:
[Unit]
Description=My Spring Boot App
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -Xms512m -Xmx512m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -jar myapp.jar
Restart=always
RestartSec=10
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
执行:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
2. Docker 部署注意事项
如果使用 Docker,务必在 docker run 或 docker-compose.yml 中显式传递 JVM 参数,否则容器内的 Java 可能无法正确识别内存限制。
# docker-compose.yml 示例
version: '3'
services:
app:
image: openjdk:17-slim
deploy:
resources:
limits:
memory: 1.8G # 限制容器内存
command: >
java -Xms512m -Xmx512m -XX:MaxMetaspaceSize=128m
-XX:+UseG1GC
-jar app.jar
environment:
- JAVA_OPTS=-Xms512m -Xmx512m
总结 Checklist
| 优化项 | 关键动作 | 目标数值参考 |
|---|---|---|
| JVM Heap | 强制指定 Xmx/Xms | 512MB (占物理内存 ~30%) |
| Metaspace | 限制元空间 | 128MB |
| GC 算法 | 选用 G1 或 Serial | -XX:+UseG1GC |
| Swap | 创建 Swap 文件 | 2GB – 4GB |
| Swappiness | 降低交换优先级 | 10 |
| File Descriptors | 提高 ulimit | 65535 |
| DB Pool | 限制连接数 | 10 |
通过以上配置,2 核 2G 的服务器完全可以稳定运行轻量级或中等负载的 Spring Boot 应用。如果业务量激增,请优先考虑升级服务器配置或使用云函数/容器化集群拆分服务。
轻量云Cloud