Nginx + Tomcat 整合实战(五):性能优化与缓存策略

系列导读:本篇将深入讲解 Nginx + Tomcat 架构的性能优化策略,包括静态资源优化、缓存配置、JVM 调优、连接池优化等核心技能。



前言:性能优化的重要性

未经优化的 Nginx + Tomcat 架构,往往存在以下性能瓶颈:

🚫 静态资源由 Tomcat 处理,性能浪费
🚫 无缓存机制,重复请求消耗资源
🚫 JVM 内存配置不当,频繁 GC
🚫 连接池配置不合理,连接等待
🚫 数据库查询慢,响应时间长

优化效果对比

指标优化前优化后提升
QPS5005000+10x
响应时间500ms50ms10x
CPU 利用率90%40%节省 50%
内存使用4GB1.5GB节省 62%

一、静态资源优化

1.1 动静分离原理

┌─────────────────────────────────────────────────────────────┐
│                      客户端请求                              │
└─────────────────────────┬───────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│                      Nginx (80)                              │
│  ┌─────────────────────┐    ┌─────────────────────────────┐ │
│  │   静态资源处理       │    │      动态请求转发           │ │
│  │   .css/.js/.jpg     │    │   proxy_pass → Tomcat       │ │
│  │   性能提升 10x+     │    │   专注业务逻辑              │ │
│  └─────────────────────┘    └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

1.2 Nginx 静态资源配置

server {
    listen 80;
    server_name static.example.com;
    
    # 静态资源根目录
    root /opt/tomcat/current/webapps/ROOT;
    
    # ==================== 图片资源 ====================
    location ~* \.(jpg|jpeg|png|gif|ico|webp|svg)$ {
        expires 1y;  # 缓存 1 年
        add_header Cache-Control "public, immutable";
        access_log off;  # 不记录日志
        
        # 开启文件缓存
        open_file_cache max=10000 inactive=30s;
        open_file_cache_valid 60s;
        open_file_cache_min_uses 2;
    }
    
    # ==================== CSS/JS ====================
    location ~* \.(css|js)$ {
        expires 30d;  # 缓存 30 天
        add_header Cache-Control "public";
        access_log off;
        
        # Gzip 压缩
        gzip_static on;  # 使用预压缩文件
    }
    
    # ==================== 字体文件 ====================
    location ~* \.(woff|woff2|ttf|otf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Access-Control-Allow-Origin "*";
        access_log off;
    }
    
    # ==================== 媒体文件 ====================
    location ~* \.(mp4|webm|mp3|ogg|wav)$ {
        expires 30d;
        add_header Cache-Control "public";
        
        # 限速(可选)
        limit_rate 1m;  # 限制下载速度 1MB/s
    }
}

1.3 静态资源压缩

http {
    # ==================== Gzip 压缩配置 ====================
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;  # 压缩级别 1-9
    gzip_min_length 1024;  # 大于 1KB 才压缩
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    
    # 压缩类型
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/x-javascript
        application/xml
        application/xml+rss
        application/json
        application/x-font-ttf
        image/svg+xml;
    
    # 禁用压缩(IE6)
    gzip_disable "msie6";
}

1.4 预压缩文件

# 生成预压缩文件
find /opt/tomcat/current/webapps/ROOT -type f \( -name "*.css" -o -name "*.js" \) -exec gzip -k {} \;

# Nginx 配置使用预压缩
location ~* \.(css|js)$ {
    gzip_static on;  # 优先使用 .gz 文件
    expires 30d;
}

二、Nginx 缓存策略

2.1 浏览器缓存

server {
    # ==================== 缓存控制策略 ====================
    
    # 不缓存的资源
    location ~* \.(html|jsp|do|action)$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
    }
    
    # 短期缓存
    location ~* \.(json|xml)$ {
        expires 5m;
        add_header Cache-Control "public, max-age=300";
    }
    
    # 长期缓存(带版本号/哈希的静态资源)
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

2.2 代理缓存

# ==================== 缓存路径配置 ====================
proxy_cache_path /var/cache/nginx/api
    levels=1:2                    # 目录层级
    keys_zone=api_cache:100m      # 缓存区名称和大小
    max_size=10g                  # 最大缓存大小
    inactive=60m                  # 不活跃删除时间
    use_temp_path=off;            # 不使用临时目录

server {
    listen 80;
    server_name api.example.com;

    # ==================== API 缓存 ====================
    location /api/products {
        proxy_pass http://tomcat_backend;
        
        # 启用缓存
        proxy_cache api_cache;
        
        # 缓存键
        proxy_cache_key "$scheme$request_method$host$request_uri";
        
        # 缓存有效期
        proxy_cache_valid 200 10m;    # 成功响应缓存 10 分钟
        proxy_cache_valid 404 1m;     # 404 缓存 1 分钟
        proxy_cache_valid any 5s;     # 其他响应缓存 5 秒
        
        # 添加缓存状态头
        add_header X-Cache-Status $upstream_cache_status;
        
        # 后端不可用时使用过期缓存
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        
        # 缓存锁(防止缓存击穿)
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;
        
        # 不缓存的请求
        proxy_cache_bypass $http_pragma $http_authorization;
    }
    
    # ==================== 不缓存动态接口 ====================
    location /api/user {
        proxy_pass http://tomcat_backend;
        proxy_cache off;  # 禁用缓存
    }
}

2.3 FastCGI 缓存(PHP 应用)

fastcgi_cache_path /var/cache/nginx/fastcgi
    levels=1:2
    keys_zone=fastcgi_cache:50m
    max_size=5g
    inactive=30m
    use_temp_path=off;

server {
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        
        # FastCGI 缓存
        fastcgi_cache fastcgi_cache;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_cache_valid 200 10m;
        
        add_header X-FastCGI-Cache $upstream_cache_status;
    }
}

2.4 缓存清理

# 手动清理缓存端点
location /purge_cache {
    allow 127.0.0.1;
    deny all;
    
    # 需要 ngx_cache_purge 模块
    proxy_cache_purge api_cache "$scheme$request_method$host$request_uri";
}
# 定时清理脚本
# crontab -e
0 3 * * * find /var/cache/nginx -type f -mtime +7 -delete

三、Tomcat 性能调优

3.1 Connector 配置优化

<!-- Tomcat conf/server.xml -->
<Connector port="8080" 
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           
           <!-- 线程配置 -->
           maxThreads="500"           <!-- 最大线程数 -->
           minSpareThreads="50"       <!-- 最小空闲线程 -->
           maxSpareThreads="200"      <!-- 最大空闲线程 -->
           acceptCount="200"          <!-- 等待队列长度 -->
           
           <!-- 连接配置 -->
           connectionTimeout="20000"  <!-- 连接超时 -->
           keepAliveTimeout="60000"   <!-- 长连接超时 -->
           maxKeepAliveRequests="100" <!-- 长连接最大请求数 -->
           
           <!-- 性能优化 -->
           enableLookups="false"      <!-- 禁用 DNS 反查 -->
           disableUploadTimeout="true"
           URIEncoding="UTF-8"
           
           <!-- 压缩配置 -->
           compression="on"
           compressionMinSize="2048"
           compressibleMimeType="text/html,text/xml,text/css,application/json,application/javascript"
           
           <!-- NIO 配置 -->
           pollerThreadCount="2"      <!-- 轮询线程数 -->
           selectorTimeout="1000"     <!-- 选择器超时 -->
/>

3.2 线程池配置

<!-- 自定义线程池 -->
<Executor name="tomcatThreadPool" 
          namePrefix="tomcat-http-"
          maxThreads="500"
          minSpareThreads="50"
          maxIdleTime="60000"
          maxQueueSize="100"/>

<!-- Connector 使用线程池 -->
<Connector executor="tomcatThreadPool"
           port="8080"
           protocol="HTTP/1.1"
           ... />

3.3 APR/Native 配置

# 安装 APR
sudo yum install -y apr apr-devel apr-util apr-util-devel
# 或
sudo apt install -y libapr1 libapr1-dev

# 安装 Tomcat Native
cd /opt/tomcat/current/bin
tar -xzf tomcat-native.tar.gz
cd tomcat-native-*/native
./configure --with-apr=/usr/bin/apr-1-config
make && make install

# 配置环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib
<!-- 使用 APR Connector -->
<Connector port="8080" 
           protocol="org.apache.coyote.http11.Http11AprProtocol"
           ... />

3.4 连接器选择

连接器说明适用场景
BIO阻塞 I/O(已废弃)不推荐
NIO非阻塞 I/O通用场景(推荐)
APR本地库,性能最佳高性能场景
NIO2异步 I/O高并发场景

四、JVM 内存优化

4.1 JVM 内存模型

┌─────────────────────────────────────────────────────────────┐
│                        JVM 内存                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    堆内存 (Heap)                      │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │   │
│  │  │   新生代     │  │   老年代     │  │   元空间     │  │   │
│  │  │  (Young)    │  │  (Old)      │  │  (Metaspace)│  │   │
│  │  │  Eden+S0+S1 │  │             │  │             │  │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  │   │
│  └─────────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                  非堆内存 (Non-Heap)                  │   │
│  │  线程栈、直接内存、代码缓存等                          │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

4.2 JVM 参数配置

# Tomcat bin/setenv.sh
#!/bin/bash

# ==================== 内存配置 ====================
# 堆内存(根据服务器内存调整,建议不超过物理内存的 50%)
JAVA_OPTS="-Xms2g -Xmx2g"

# 新生代大小(堆内存的 1/3 到 1/4)
JAVA_OPTS="$JAVA_OPTS -Xmn512m"

# 元空间大小(JDK 8+)
JAVA_OPTS="$JAVA_OPTS -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m"

# ==================== GC 配置 ====================
# 使用 G1 垃圾收集器(JDK 9+ 默认,JDK 8 推荐)
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"

# G1 配置
JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=200"  # 最大 GC 停顿时间
JAVA_OPTS="$JAVA_OPTS -XX:G1HeapRegionSize=16m"  # Region 大小
JAVA_OPTS="$JAVA_OPTS -XX:InitiatingHeapOccupancyPercent=45"  # 触发并发 GC 的堆占用率

# 或使用 Parallel GC(吞吐量优先)
# JAVA_OPTS="$JAVA_OPTS -XX:+UseParallelGC -XX:ParallelGCThreads=4"

# ==================== GC 日志 ====================
JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:file=/opt/tomcat/logs/gc.log:time,uptime:filecount=5,filesize=10m"

# ==================== 性能优化 ====================
# 字符串去重
JAVA_OPTS="$JAVA_OPTS -XX:+UseStringDeduplication"

# 压缩指针
JAVA_OPTS="$JAVA_OPTS -XX:+UseCompressedOops"

# 大页内存(可选)
# JAVA_OPTS="$JAVA_OPTS -XX:+UseLargePages"

# ==================== 故障诊断 ====================
# OOM 时生成堆转储
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/opt/tomcat/logs/heapdump.hprof"

# 发生 OOM 时执行脚本
JAVA_OPTS="$JAVA_OPTS -XX:OnOutOfMemoryError='/opt/tomcat/bin/restart.sh'"

# ==================== 远程调试(开发环境)====================
# JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"

# ==================== JMX 监控 ====================
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9010"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"

export JAVA_OPTS

4.3 内存配置建议

服务器内存堆内存新生代元空间
4GB2GB512MB128MB
8GB4GB1GB256MB
16GB8GB2GB256MB
32GB16GB4GB512MB

4.4 GC 日志分析

# 查看 GC 日志
tail -f /opt/tomcat/logs/gc.log

# 使用 GCViewer 分析
# https://github.com/chewiebug/GCViewer

# 使用 GCEasy 在线分析
# https://gceasy.io/

五、数据库连接池优化

5.1 HikariCP 配置(推荐)

# application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.100:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: yourpassword
    
    hikari:
      # 连接池大小
      maximum-pool-size: 20        # 最大连接数
      minimum-idle: 5              # 最小空闲连接
      
      # 超时配置
      connection-timeout: 30000    # 连接超时(毫秒)
      idle-timeout: 600000         # 空闲超时(毫秒)
      max-lifetime: 1800000        # 连接最大生命周期(毫秒)
      
      # 连接测试
      validation-timeout: 5000     # 验证超时
      leak-detection-threshold: 60000  # 连接泄露检测
      
      # 性能优化
      pool-name: TomcatHikariPool

5.2 Druid 配置

# application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.100:3306/mydb
    username: root
    password: yourpassword
    type: com.alibaba.druid.pool.DruidDataSource
    
    druid:
      # 连接池配置
      initial-size: 5
      min-idle: 5
      max-active: 20
      max-wait: 60000
      
      # 连接检测
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      
      # 监控配置
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin
      
      # 慢查询监控
      filter:
        stat:
          enabled: true
          slow-sql-millis: 3000
          log-slow-sql: true

5.3 连接池大小计算

连接数 = (核心数 * 2) + 有效磁盘数

示例:
4 核 CPU + 1 块磁盘 = (4 * 2) + 1 = 9 个连接

建议范围:10-20 个连接

六、综合性能测试

6.1 测试工具

# 安装 Apache Bench
sudo yum install -y httpd-tools  # CentOS
sudo apt install -y apache2-utils  # Ubuntu

# 安装 wrk
git clone https://github.com/wg/wrk.git
cd wrk && make
sudo cp wrk /usr/local/bin/

6.2 压测脚本

#!/bin/bash
# performance_test.sh

URL="http://app.example.com/api/products"
CONCURRENT=(50 100 200 500)
REQUESTS=10000

echo "========== 性能测试开始 =========="
echo "目标 URL: $URL"
echo "总请求数: $REQUESTS"
echo ""

for c in "${CONCURRENT[@]}"; do
    echo "---------- 并发数: $c ----------"
    ab -n $REQUESTS -c $c $URL
    echo ""
    sleep 5
done

echo "========== 性能测试结束 =========="

6.3 性能指标

指标说明优化目标
QPS每秒请求数越高越好
响应时间请求处理时间< 100ms
并发数同时处理请求数越高越好
错误率失败请求比例< 0.1%
CPU 使用率CPU 占用< 70%
内存使用率内存占用< 80%

6.4 监控工具

# 系统监控
top -p $(pgrep java)  # 监控 Java 进程
vmstat 1              # 内存统计
iostat 1              # I/O 统计
netstat -anp | grep 8080  # 网络连接

# JVM 监控
jstat -gcutil <pid> 1000  # GC 统计
jmap -heap <pid>          # 堆内存信息
jstack <pid>              # 线程栈

# 可视化工具
# JConsole、VisualVM、Arthas

总结

本文深入讲解了 Nginx + Tomcat 架构的性能优化策略:

静态资源优化:动静分离、压缩、缓存
Nginx 缓存:浏览器缓存、代理缓存、缓存清理
Tomcat 调优:Connector 配置、线程池、APR
JVM 优化:内存配置、GC 调优、监控
连接池优化:HikariCP、Druid 配置
性能测试:压测工具、监控指标

优化检查清单

□ 静态资源由 Nginx 处理
□ Gzip 压缩已启用
□ 浏览器缓存已配置
□ 代理缓存已配置(适用场景)
□ Tomcat Connector 已优化
□ JVM 内存已合理配置
□ GC 策略已选择
□ 数据库连接池已优化
□ 性能测试已完成
□ 监控已部署

下一篇预告:(Nginx + Tomcat 整合实战(六):安全加固与生产部署),将深入讲解 HTTPS 配置、安全防护、日志监控、自动化部署等核心技能。


作者:刘~浪地球
系列:Nginx + Tomcat 整合实战(五)
更新时间:2026-04-01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘~浪地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值