在 2 核 2G(2 vCPU, 2GB RAM)的服务器上运行 Spring Boot 应用,资源确实比较紧张。Spring Boot 默认配置通常是为服务器环境设计的,直接启动很容易导致内存溢出(OOM)或 CPU 飙升。
以下是针对该配置的核心优化方案,按优先级排序:
1. JVM 内存参数调优(最关键)
2GB 内存中,操作系统和后台进程(如 Nginx、数据库连接池等)需要占用一部分,留给 Java 堆内存的空间非常有限。如果设置过大,JVM 会频繁进行 Full GC 甚至被系统 OOM Killer 杀掉。
- 限制最大堆内存:建议将
-Xmx设置为物理内存的 50%-60% 左右。- 推荐值:
-Xmx512m或-Xms512m。 - 原因:保留约 1GB 给非堆内存(Metaspace、线程栈、Direct Buffer)和操作系统缓存。
- 推荐值:
- 固定初始堆大小:使用
-Xms与-Xmx保持一致,避免 JVM 在运行时动态调整堆大小带来的性能抖动。 - 元空间优化:
-XX:MaxMetaspaceSize=128m,防止类加载过多导致元空间溢出。 - GC 策略选择:
- Java 8:默认 G1 可能开销略大,可尝试
-XX:+UseConcMarkSweepGC(CMS) 或保持 G1 但调整参数。 - Java 11+:默认 ZGC 或 Shenandoah 在低内存下可能不如 G1 稳定,建议使用 G1 并开启
-XX:+UseG1GC。 - 通用推荐命令:
java -Xms512m -Xmx512m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar app.jar
- Java 8:默认 G1 可能开销略大,可尝试
2. 关闭不必要的自动配置
Spring Boot 的“约定优于配置”特性虽然方便,但在低配环境下会加载大量不需要的组件(如 Actuator、Thymeleaf、消息队列客户端等),增加启动时间和内存占用。
- 排除无关 Starter:在
pom.xml或build.gradle中注释掉不用的依赖。 - 自定义 ApplicationRunner:在
application.properties/yml中指定只启用必要的模块,或者通过@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})排除特定自动配置。 - 禁用 Actuator 端点:如果不需要监控,完全移除
spring-boot-starter-actuator,或者仅暴露极少的端点。
3. 应用层代码与配置优化
- Tomcat 线程池调优:
Tomcat 默认线程数较大,每个线程消耗一定内存。对于 2 核机器,并发量通常不高。- 配置示例 (
application.yml):server: tomcat: threads: max: 200 # 默认通常是 200,可适当降低到 100-150 min-spare: 10 max-connections: 2000 compression: enabled: true
- 配置示例 (
- 连接池优化:
如果使用 HikariCP(Spring Boot 默认),确保最大连接数不要超过数据库服务器的承受能力,也不要设得太大(例如设为 10-20 即可)。spring: datasource: hikari: maximum-pool-size: 15 minimum-idle: 5 - 关闭开发模式特性:
确保spring.profiles.active不是dev,因为开发模式下会开启热部署、详细的错误页面(ErrorPageFilter)等,增加内存消耗。
4. 外部依赖与架构优化
- 引入轻量级缓存:
如果应用中有大量重复查询,引入 Redis(如果内存允许)或本地缓存(Caffeine)。Caffeine 比 Ehcache 更轻量且性能更好。 - 异步处理:
将耗时操作(发送邮件、生成报表、调用第三方 API)改为异步执行(@Async),减少主线程阻塞,提高吞吐量。 - Nginx 反向X_X:
务必在应用前加一层 Nginx。利用 Nginx 处理静态资源、SSL 卸载和限流,减轻 Spring Boot 的压力。
5. 操作系统层面优化
- Swap 分区管理:
2G 内存非常危险,建议分配 1GB 左右的 Swap 分区作为缓冲,防止因瞬时内存峰值导致进程被杀。- 检查:
free -h - 创建 Swap(如果需要):
fallocate -l 1G /swapfile->chmod 600 /swapfile->mkswap /swapfile->swapon /swapfile。 - 注意:Swapping 会降低性能,只是保命手段,核心还是要靠 JVM 调优。
- 检查:
- 文件描述符限制:
修改/etc/security/limits.conf,增加nofile限制,防止高并发下报错 "Too many open files"。* soft nofile 65535 * hard nofile 65535 - 内核参数优化:
适当调整 TCP 连接相关的内核参数(net.ipv4.tcp_tw_reuse,net.core.somaxconn等),提升网络处理能力。
6. 部署与监控建议
- 使用 Docker 资源限制:
如果使用 Docker,务必在docker run或docker-compose中明确限制容器资源,防止 JVM 误判宿主机内存而申请过多。deploy: resources: limits: cpus: '2' memory: 2G(注意:此时 JVM 参数中的
-Xmx仍需手动配合,不能只依赖 Docker 限制) - 监控告警:
安装轻量级监控(如 Prometheus + Node Exporter + Grafana,或者简单的 Shell 脚本),监控内存使用率和 GC 频率。一旦发现 GC 频繁(Full GC 次数激增),立即扩容或进一步排查代码瓶颈。
总结 Checklist
- [ ] JVM: 设置
-Xms512m -Xmx512m,固定堆大小。 - [ ] 配置: 移除无用 Starter,关闭 Dev 模式。
- [ ] Tomcat: 限制线程数至 100-150。
- [ ] DB: 限制连接池大小至 15-20。
- [ ] OS: 配置 Swap,调整文件句柄限制。
- [ ] 架构: 前置 Nginx 处理静态资源。
通过以上调整,2 核 2G 的服务器通常可以流畅运行中等负载的 Spring Boot 业务系统。如果业务逻辑极其复杂或并发极高,则必须考虑升级硬件或进行微服务拆分。
CLOUD技术博