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

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


文章目录

    • 前言:性能优化的重要性
    • 一、静态资源优化
      • [1.1 动静分离原理](#1.1 动静分离原理)
      • [1.2 Nginx 静态资源配置](#1.2 Nginx 静态资源配置)
      • [1.3 静态资源压缩](#1.3 静态资源压缩)
      • [1.4 预压缩文件](#1.4 预压缩文件)
    • [二、Nginx 缓存策略](#二、Nginx 缓存策略)
      • [2.1 浏览器缓存](#2.1 浏览器缓存)
      • [2.2 代理缓存](#2.2 代理缓存)
      • [2.3 FastCGI 缓存(PHP 应用)](#2.3 FastCGI 缓存(PHP 应用))
      • [2.4 缓存清理](#2.4 缓存清理)
    • [三、Tomcat 性能调优](#三、Tomcat 性能调优)
      • [3.1 Connector 配置优化](#3.1 Connector 配置优化)
      • [3.2 线程池配置](#3.2 线程池配置)
      • [3.3 APR/Native 配置](#3.3 APR/Native 配置)
      • [3.4 连接器选择](#3.4 连接器选择)
    • [四、JVM 内存优化](#四、JVM 内存优化)
      • [4.1 JVM 内存模型](#4.1 JVM 内存模型)
      • [4.2 JVM 参数配置](#4.2 JVM 参数配置)
      • [4.3 内存配置建议](#4.3 内存配置建议)
      • [4.4 GC 日志分析](#4.4 GC 日志分析)
    • 五、数据库连接池优化
      • [5.1 HikariCP 配置(推荐)](#5.1 HikariCP 配置(推荐))
      • [5.2 Druid 配置](#5.2 Druid 配置)
      • [5.3 连接池大小计算](#5.3 连接池大小计算)
    • 六、综合性能测试
      • [6.1 测试工具](#6.1 测试工具)
      • [6.2 压测脚本](#6.2 压测脚本)
      • [6.3 性能指标](#6.3 性能指标)
      • [6.4 监控工具](#6.4 监控工具)
    • 总结

前言:性能优化的重要性

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

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

优化效果对比

指标 优化前 优化后 提升
QPS 500 5000+ 10x
响应时间 500ms 50ms 10x
CPU 利用率 90% 40% 节省 50%
内存使用 4GB 1.5GB 节省 62%

一、静态资源优化

1.1 动静分离原理

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

1.2 Nginx 静态资源配置

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 静态资源压缩

nginx 复制代码
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 预压缩文件

bash 复制代码
# 生成预压缩文件
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 浏览器缓存

nginx 复制代码
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 代理缓存

nginx 复制代码
# ==================== 缓存路径配置 ====================
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 应用)

nginx 复制代码
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 缓存清理

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

三、Tomcat 性能调优

3.1 Connector 配置优化

xml 复制代码
<!-- 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 线程池配置

xml 复制代码
<!-- 自定义线程池 -->
<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 配置

bash 复制代码
# 安装 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
xml 复制代码
<!-- 使用 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 参数配置

bash 复制代码
# 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 内存配置建议

服务器内存 堆内存 新生代 元空间
4GB 2GB 512MB 128MB
8GB 4GB 1GB 256MB
16GB 8GB 2GB 256MB
32GB 16GB 4GB 512MB

4.4 GC 日志分析

bash 复制代码
# 查看 GC 日志
tail -f /opt/tomcat/logs/gc.log

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

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

五、数据库连接池优化

5.1 HikariCP 配置(推荐)

yaml 复制代码
# 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 配置

yaml 复制代码
# 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 测试工具

bash 复制代码
# 安装 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 压测脚本

bash 复制代码
#!/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 监控工具

bash 复制代码
# 系统监控
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

相关推荐
小百菜1 天前
Keepalived + Nginx 实现高可用
nginx·keepalived
lclcooky1 天前
Spring 中使用Mybatis,超详细
spring·tomcat·mybatis
驾驭人生1 天前
ASP.NET Core 实现 SSE 服务器推送|生产级实战教程(含跨域 / Nginx / 前端完整代码)
服务器·前端·nginx
CSharp精选营1 天前
.NET 8 性能优化实战:让你的应用起飞
性能优化·c#·.net·技术干货
Linux运维技术栈1 天前
生产环境Certbot泛域名证书全自动续期完整配置指南(Cloudflare DNS验证)
nginx·证书·ssl
SeSs IZED1 天前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx
SuperEugene1 天前
Vue3 性能优化规范:日常必做优化(不玄学、可落地)|可维护性与兜底规范篇
开发语言·前端·javascript·vue.js·性能优化·前端框架
API快乐传递者1 天前
从零构建高可用API接口:架构设计、性能优化与安全实践
安全·性能优化
山峰哥1 天前
告别“点点点”:AI 如何重构我们的测试体系与质量防线
服务器·汇编·数据库·人工智能·性能优化·重构
weixin199701080161 天前
《XMZ 商品详情页前端性能优化实战》
前端·性能优化