系列导读:本篇将深入讲解 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