小型Spring Boot服务在Ubuntu 2G内存服务器上的性能优化建议

针对2GB内存的Ubuntu服务器运行Spring Boot服务,以下是一套完整的性能优化方案:

一、JVM优化配置

1. 内存分配策略

# application.properties或启动参数
java -jar -Xms512m -Xmx1024m 
-XX:MaxMetaspaceSize=128m 
-XX:ReservedCodeCacheSize=64m 
-XX:+UseCompressedOops 
-XX:+UseCompressedClassPointers 
-XX:+UseG1GC 
-XX:MaxGCPauseMillis=200 
-XX:InitiatingHeapOccupancyPercent=35 
-XX:ParallelGCThreads=2 
-XX:ConcGCThreads=1 
your-app.jar

2. 推荐配置组合

# 生产环境推荐(Spring Boot 2.3+)
java -jar -Xms768m -Xmx1536m 
-XX:MaxMetaspaceSize=256m 
-XX:+UseG1GC 
-XX:MaxGCPauseMillis=150 
-XX:InitiatingHeapOccupancyPercent=45 
-XX:+AlwaysPreTouch 
-XX:+UseStringDeduplication 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/var/log/heapdump.hprof 
-Dspring.profiles.active=prod 
-Djava.security.egd=file:/dev/./urandom 
-Dfile.encoding=UTF-8 
your-app.jar

二、Spring Boot应用层优化

1. 应用配置优化

# application-prod.yml
server:
  tomcat:
    max-connections: 1000
    max-threads: 50           # 根据CPU核心数调整
    min-spare-threads: 10
    connection-timeout: 5000ms
    keep-alive-timeout: 30000ms
    max-keep-alive-requests: 100
    accept-count: 50

  compression:
    enabled: true
    mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/json
    min-response-size: 1024

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

  jackson:
    default-property-inclusion: non_null

  mvc:
    async:
      request-timeout: 30000

2. 依赖优化

<!-- pom.xml 移除不必要的依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 排除Tomcat使用undertow -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 使用Undertow替代Tomcat(内存更友好) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

三、操作系统优化

1. 系统参数调整

# /etc/sysctl.conf 添加
vm.swappiness = 10
vm.vfs_cache_pressure = 50
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30

# 生效配置
sudo sysctl -p

2. 内存管理

# 清理缓存
echo 3 > /proc/sys/vm/drop_caches

# 监控内存使用
sudo apt install htop
htop  # 实时监控

四、监控与诊断

1. 健康检查端点

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,info,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

2. 监控脚本

#!/bin/bash
# monitor.sh
APP_PID=$(pgrep -f "your-app.jar")

# 内存监控
jstat -gc $APP_PID 1000

# 线程监控
jstack $APP_PID > thread_dump_$(date +%s).txt

# GC日志分析
java -jar -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags:filecount=5,filesize=10m ...

五、部署优化

1. 使用Docker容器化

FROM openjdk:11-jre-slim
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

# 使用非root用户
RUN useradd -ms /bin/bash spring
USER spring

COPY --chown=spring:spring target/*.jar app.jar

# JVM优化参数
ENV JAVA_OPTS="-Xmx1536m -Xms768m -XX:+UseG1GC"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app.jar"]

2. 服务管理(systemd)

# /etc/systemd/system/springboot.service
[Unit]
Description=Spring Boot Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/app
ExecStart=/usr/bin/java -jar -Xmx1536m -Xms768m app.jar
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
LimitNPROC=4096

[Install]
WantedBy=multi-user.target

六、数据库与缓存优化

1. 连接池配置

spring:
  datasource:
    hikari:
      maximum-pool-size: 10          # 小内存服务器建议5-15
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      leak-detection-threshold: 60000

2. 缓存策略

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(1000)        // 控制缓存条目数量
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .recordStats());
        return cacheManager;
    }
}

七、应急处理方案

1. OOM自动重启脚本

#!/bin/bash
# oom-monitor.sh
APP_NAME="your-app"
MAX_MEMORY_PERCENT=85

while true; do
    MEM_USAGE=$(free | awk '/Mem:/ {printf("%.0f"), $3/$2*100}')

    if [ $MEM_USAGE -gt $MAX_MEMORY_PERCENT ]; then
        echo "$(date): Memory usage ${MEM_USAGE}% > ${MAX_MEMORY_PERCENT}%, restarting..."
        systemctl restart $APP_NAME
        sleep 60
    fi

    sleep 30
done

2. 快速诊断命令

# 查看JVM内存
jcmd <pid> VM.native_memory summary

# 查看线程状态
jstack <pid> | grep -c "RUNNABLE"

# 查看GC情况
jstat -gcutil <pid> 1000 10

关键建议总结:

  1. JVM堆内存:建议最大堆1.5GB,留500MB给系统和其他进程
  2. GC选择:G1GC在2GB内存下表现较好
  3. 线程池:Tomcat线程数建议50以内
  4. 连接池:数据库连接数控制在10左右
  5. 监控:必须开启健康检查和基础监控
  6. 容器化:使用slim镜像减少内存占用
  7. 定期重启:可设置每日低峰期重启释放内存

通过以上优化,2GB内存服务器通常可以稳定支撑中小型Spring Boot应用(日PV 1-10万级别)。建议先进行压力测试,根据实际表现调整参数。

云服务器