Py学习  »  NGINX

Tomcat/Nginx 参数调优:让你的服务器吞吐量翻倍的秘密

马哥Linux运维 • 4 月前 • 192 次点击  

Tomcat/Nginx 参数调优:让你的服务器吞吐量翻倍的秘密

一、概述

1.1 背景介绍

Tomcat 和 Nginx 作为 Java Web 应用和反向代理的黄金组合,在生产环境中承载着海量的用户请求。然而,大多数开发者往往采用默认配置直接上线,导致在高并发场景下出现响应缓慢、连接超时、CPU 飙升等问题。通过科学的参数调优,可以在不增加硬件成本的情况下,将系统吞吐量提升2-5倍,显著改善用户体验。

1.2 技术特点

  • • Tomcat 调优:线程池、连接器、JVM参数等多维度优化,适配不同业务场景
  • • Nginx 调优:工作进程、事件模型、缓存策略等核心参数精细化配置
  • • 协同优化:前后端联动调优,最大化发挥架构优势
  • • 性能监控:建立可视化监控体系,实时掌握系统健康状态

1.3 适用场景

  • • 场景一:电商大促、秒杀活动等高并发峰值场景,需要承载数十万QPS
  • • 场景二:微服务架构下的 API 网关,需要高效转发大量后端请求
  • • 场景三:静态资源密集型站点,需要优化缓存和传输效率
  • • 场景四:长连接场景(WebSocket、SSE),需要支持海量并发连接

1.4 环境要求

组件
版本要求
说明
操作系统
CentOS 7+/Ubuntu 20.04+
Linux 内核 3.10+
Tomcat
9.0+/10.0+
推荐最新稳定版
Nginx
1.20+
建议使用 Tengine 或 OpenResty
JDK
OpenJDK 11/17
LTS 版本
硬件配置
4核8GB+
建议 SSD,万兆网卡

二、详细步骤

2.1 Tomcat 核心参数调优

◆ 2.1.1 Connector 连接器优化

Tomcat 的 Connector 决定了如何接收和处理请求,是性能调优的第一关。


<Connectorport="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="800"
minSpareThreads="50"
maxConnections="10000"
acceptCount="1000"
connectionTimeout="20000"
keepAliveTimeout="60000"
maxKeepAliveRequests="100"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"
URIEncoding="UTF-8"
enableLookups="false"
disableUploadTimeout="true"
maxHttpHeaderSize="8192"
redirectPort="8443" />

参数说明:

  • • protocol:协议类型
    • • Http11NioProtocol:NIO 模式(推荐),适合高并发
    • • Http11Nio2Protocol:NIO2 模式,适合长连接场景
    • • Http11AprProtocol:APR 模式,性能最佳但需要安装 native 库
  • • maxThreads:最大工作线程数
    • • 默认值:200
    • • 推荐值:CPU核心数 × 100~200(4核配置400~800)
    • • 计算公式:maxThreads = (QPS × 响应时间) / 1000
    • • 注意:过大会增加线程切换开销,需结合实际压测
  • • minSpareThreads:最小空闲线程数
    • • 推荐值:maxThreads 的 10%~20%
    • • 作用:预热线程池,减少冷启动时的延迟
  • • maxConnections:最大连接数
    • • 默认值:10000(NIO模式)
    • • 推荐值:maxThreads 的 10~20 倍
    • • 原理:连接数 > 线程数时,多余连接等待线程释放
  • • acceptCount:等待队列长度
    • • 默认值:100
    • • 推荐值:1000~2000
    • • 注意:达到 maxConnections 后,新连接进入此队列等待
  • • connectionTimeout:连接超时时间(毫秒)
    • • 默认值 :20000(20秒)
    • • 推荐值:20000~60000
    • • 说明:客户端建立连接后,必须在此时间内发送数据
  • • keepAliveTimeout:Keep-Alive 超时时间(毫秒)
    • • 默认值:connectionTimeout
    • • 推荐值:60000~120000
    • • 优化点:启用 Keep-Alive 可复用连接,减少握手开销
  • • compression:是否开启 gzip 压缩
    • • 推荐值:on
    • • 效果:可将文本内容压缩至原大小的 20%~30%
    • • 注意:仅压缩指定 MIME 类型,图片视频等已压缩内容无需再压缩

◆ 2.1.2 Executor 线程池配置

独立配置线程池,提供更精细的控制:


<Executorname="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="800"
minSpareThreads="50"
maxIdleTime="60000"
prestartminSpareThreads="true"
maxQueueSize="1000" />

<Connectorport="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
executor="tomcatThreadPool"
... />

参数说明:

  • • maxQueueSize:任务队列长度,超出则拒绝请求
  • • prestartminSpareThreads:启动时预创建最小线程数
  • • maxIdleTime:线程空闲超时时间,超时则回收

◆ 2.1.3 JVM 参数优化

# catalina.sh 或 setenv.sh
JAVA_OPTS="$JAVA_OPTS -Xms4g -Xmx4g"
JAVA_OPTS="$JAVA_OPTS -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
JAVA_OPTS="$JAVA_OPTS -XX:+ParallelRefProcEnabled"
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/var/log/tomcat/heap_dump.hprof"
JAVA_OPTS="$JAVA_OPTS -Xloggc:/var/log/tomcat/gc.log"
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
JAVA_OPTS="$JAVA_OPTS -Duser.timezone=Asia/Shanghai"

参数说明:

  • • -Xms/-Xmx:堆内存大小,建议设置为相同值,避免动态扩容
    • • 推荐值:物理内存的 50%~70%
    • • 4核8GB:设置 4g
    • • 8核16GB:设置 10g~12g
  • • -XX:+UseG1GC:使用 G1 垃圾回收器(JDK 9+ 默认)
    • • 优点:低延迟,适合大堆内存场景
    • • 替代方案:ZGC(JDK 15+),适合超大堆(>100GB)
  • • -Djava.security.egd=file:/dev/./urandom:使用非阻塞随机数生成器
    • • 问题:Linux 默认 /dev/random 在熵池不足时会阻塞
    • • 效果:避免 Tomcat 启动时卡在 SecureRandom 初始化

2.2 Nginx 核心参数调优

◆ 2.2.1 全局配置优化

# nginx.conf
user nginx;
worker_processes auto;  # 自动检测CPU核心数
worker_cpu_affinity auto;  # CPU亲和性绑定
worker_rlimit_nofile65535;  # 单个worker进程最大文件描述符
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
useepoll;  # Linux下使用高性能epoll模型
worker_connections10240;  # 单个worker进程最大连接数
multi_accepton;  # 一次接受多个新连接
accept_mutexoff;  # 关闭accept互斥锁(多核推荐)
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status$body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log main buffer=64k flush=5s;

# 性能优化
sendfileon;  # 零拷贝传输文件
tcp_nopushon;  # sendfile开启时生效,减少网络报文段数量
tcp_nodelayon;  # keepalive开启时生效,禁用Nagle算法
keepalive_timeout65;  # 长连接超时时间
keepalive_requests1000;  # 单个连接最大请求数
types_hash_max_size2048;
server_tokensoff;  # 隐藏Nginx版本号

# 文件缓存
open_file_cache max=10000 inactive=60s;
open_file_cache_valid30s;
open_file_cache_min_uses2;
open_file_cache_errorson;

# Gzip压缩
gzipon;
gzip_varyon;
gzip_proxied any;
gzip_comp_level6;
gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss
               application/rss+xml font/truetype font/opentype
               application/vnd.ms-fontobject image/svg+xml;
gzip_disable"msie6";
gzip_min_length1024;  # 小于1KB不压缩

# 缓冲区设置
client_body_buffer_size128k;
client_max_body_size100m;
client_header_buffer_size4k;
large_client_header_buffers432k;
output_buffers432k;
postpone_output1460;

# 超时设置
client_header_timeout60s;
client_body_timeout60s;
send_timeout60s;

# 连接池
upstream backend {
server127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
keepalive256;  # 保持256个空闲连接到后端
keepalive_requests1000;
keepalive_timeout60s;
    }

include /etc/nginx/conf.d/*.conf;
}

参数说明:

  • • worker_processes auto:工作进程数
    • • 推荐值:auto(自动检测CPU核心数)
    • • 手动设置:等于CPU核心数,避免进程切换
  • • worker_connections:单个进程最大连接数
    • • 默认值:1024
    • • 推荐值:10240~65535
    • • 理论最大并发:worker_processes × worker_connections / 2
    • • 注意:需同时调整系统 ulimit
  • • use epoll:I/O 多路复用模型
    • • Linux:epoll(自动检测,无需手动指定)
    • • FreeBSD:kqueue
    • • Windows:不支持,使用默认 select
  • • sendfile on:零拷贝技术
    • • 原理:文件直接从磁盘发送到网卡,跳过用户空间
    • • 效果:静态文件传输性能提升 2~3 倍
  • • keepalive:后端连接池
    • • 作用:复用到 Tomcat 的连接,减少 TCP 握手
    • • 推荐值:256~512
    • • 注意:需配合 proxy_http_version 1.1 和 proxy_set_header Connection ""

◆ 2.2.2 反向代理配置




    
# conf.d/backend.conf
server {
listen80;
server_name example.com;

# 访问日志(高并发可关闭)
access_log /var/log/nginx/backend_access.log main buffer=64k;

location / {
proxy_pass http://backend;

# 代理头设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 启用HTTP/1.1和长连接
proxy_http_version1.1;
proxy_set_header Connection "";

# 超时设置
proxy_connect_timeout10s;
proxy_send_timeout60s;
proxy_read_timeout60s;

# 缓冲设置
proxy_bufferingon;
proxy_buffer_size8k;
proxy_buffers328k;
proxy_busy_buffers_size64k;

# 错误处理
proxy_next_upstreamerror timeout invalid_header http_500 http_502 http_503;
proxy_next_upstream_tries2;
proxy_next_upstream_timeout5s;
    }

# 静态资源缓存
location~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires30d;
add_header Cache-Control "public, immutable";
access_logoff;

# 如果后端有静态文件
proxy_pass http://backend;
proxy_cache static_cache;
proxy_cache_valid20030d;
proxy_cache_use_staleerror timeout updating http_500 http_502 http_503 http_504;
    }

# API接口限流
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_conn addr 10;

proxy_pass http://backend;
include proxy_params;
    }
}

# 缓存配置
proxy_cache_path /var/cache/nginx/static
                 levels=1:2
                 keys_zone=static_cache:100m
                 max_size=10g
                 inactive=7d
                 use_temp_path=off;

# 限流配置
limit_req_zone$binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_conn_zone$binary_remote_addr zone=addr:10m;

◆ 2.2.3 系统内核优化

# /etc/sysctl.conf
# 文件描述符
fs.file-max = 1000000

# 网络优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15

# TCP缓冲区
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# 应用生效
sysctl -p
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

2.3 监控和压力测试

◆ 2.3.1 安装监控工具

# Nginx状态监控
# 在nginx.conf中添加
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

# Tomcat JMX监控
# catalina.sh中添加
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9999"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"

◆ 2.3.2 压力测试

# 使用 wrk 进行压测
wrk -t8 -c1000 -d60s --latency http://example.com/

# 参数说明:
# -t8: 8个线程
# -c1000: 1000个并发连接
# -d60s: 持续60秒
# --latency: 显示延迟分布

# 预期结果:
# Requests/sec: 20000+  (QPS)
# Latency: avg<50ms, p99<200ms

三、示例代码和配置

3.1 完整配置示例

◆ 3.1.1 Tomcat 生产环境配置


"1.0" encoding="UTF-8"?>
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<GlobalNamingResources>
<Resourcename="UserDatabase"auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
GlobalNamingResources>

<Servicename="Catalina">

<Executorname="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="800"
minSpareThreads="100"
maxIdleTime="60000"
prestartminSpareThreads="true"
maxQueueSize="1000" />


<Connectorport="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
executor="tomcatThreadPool"
maxConnections="10000"
acceptCount="1000"
connectionTimeout="20000"
keepAliveTimeout="60000"
maxKeepAliveRequests ="100"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml"
URIEncoding="UTF-8"
enableLookups="false"
disableUploadTimeout="true"
maxHttpHeaderSize="8192"
redirectPort="8443"
server="Apache" />




<Enginename="Catalina"defaultHost="localhost">
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
Realm>

<Hostname="localhost"appBase="webapps"
unpackWARs="true"autoDeploy="false">


<ValveclassName="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D" />


<ValveclassName="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto" />
Host>
Engine>
Service>
Server>
# /opt/tomcat/bin/setenv.sh
#!/bin/bash

# JVM内存设置
JAVA_OPTS="$JAVA_OPTS -Xms4g -Xmx4g"
JAVA_OPTS="$JAVA_OPTS -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
JAVA_OPTS="$JAVA_OPTS -Xss512k"

# GC设置
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=200"
JAVA_OPTS="$JAVA_OPTS -XX:ParallelGCThreads=4"
JAVA_OPTS="$JAVA_OPTS -XX:ConcGCThreads=1"
JAVA_OPTS="$JAVA_OPTS -XX:InitiatingHeapOccupancyPercent=45"

# GC日志
JAVA_OPTS="$JAVA_OPTS -Xloggc:/opt/tomcat/logs/gc_%t.log"
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails"
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps"
JAVA_OPTS="$JAVA_OPTS -XX:+UseGCLogFileRotation"
JAVA_OPTS="$JAVA_OPTS -XX:NumberOfGCLogFiles=10"
JAVA_OPTS="$JAVA_OPTS -XX:GCLogFileSize=100M"

# OOM处理
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/opt/tomcat/logs/heap_dump_%p.hprof"
JAVA_OPTS="$JAVA_OPTS -XX:ErrorFile=/opt/tomcat/logs/hs_err_pid%p.log"

# 性能优化
JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"
JAVA_OPTS="$JAVA_OPTS -Duser.timezone=Asia/Shanghai"
JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"

# JMX监控
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9999"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.1.100"

export JAVA_OPTS

◆ 3.1.2 Nginx 完整配置

由于篇幅限制,完整的Nginx配置已在2.2节中展示,这里补充一个自动化部署脚本:

#!/bin/bash
# 文件名: deploy_nginx_tomcat.sh
# 功能: 一键部署和优化Nginx+Tomcat环境

set -e

echo"========== 开始部署 Nginx + Tomcat =========="

# 1. 安装依赖
yum install -y gcc gcc-c++ make zlib-devel pcre-devel openssl-devel

# 2. 编译安装Nginx
cd /tmp
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --prefix=/usr/local/nginx \
            --with-http_ssl_module \
            --with-http_v2_module \
            --with-http_realip_module \
            --with-http_stub_status_module \
            --with-http_gzip_static_module \
            --with-threads \
            --with-file-aio
make && make install

# 3. 配置Nginx
cat > /usr/local/nginx/conf/nginx.conf <<'EOF'
# 此处粘贴2.2.1节的配置
EOF

# 4. 创建systemd服务
cat > /etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=Nginx HTTP Server
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

# 5. 系统优化
cat >> /etc/sysctl.conf <<'EOF'
fs.file-max = 1000000
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
EOF
sysctl -p

cat >> /etc/security/limits.conf <<'EOF'
* soft nofile 65535
* hard nofile 65535
EOF

# 6. 启动Nginx
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx

# 7. 安装Tomcat
cd /opt
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.80/bin/apache-tomcat-9.0.80.tar.gz
tar -xzf apache-tomcat-9.0.80.tar.gz
ln -s apache-tomcat-9.0.80 tomcat

# 8. 配置Tomcat (使用之前的server.xml和setenv.sh)

# 9. 启动Tomcat
/opt/tomcat/bin/startup.sh

echo"========== 部署完成 =========="
echo"Nginx: http://your-ip"
echo"Tomcat: http://your-ip:8080"
echo"请根据实际情况调整配置文件"

3.2 实际应用案例

◆ 案例一:电商大促高并发场景

场景描述:某电商平台双11大促,预计峰值QPS达到 50000,需要保证商品详情页和下单接口的稳定性。

架构方案:

用户 -> CDN -> Nginx(4台) -> Tomcat集群(20台) -> Redis/MySQL

Nginx 配置要点:

upstream product_backend {
    least_conn;  # 最少连接数算法
server10.0.1.101:8080 weight=1 max_fails=2 fail_timeout=10s;
server10.0.1.102:8080 weight=1 max_fails=2 fail_timeout=10s;
# ... 其他18台
keepalive512 ;
}

server {
listen80;
server_name m.shop.com;

# 商品详情页缓存
location~ ^/product/(\d+)$ {
proxy_pass http://product_backend;
proxy_cache product_cache;
proxy_cache_valid2005m;  # 缓存5分钟
proxy_cache_key"$scheme$request_method$host$request_uri";
proxy_cache_use_stale updating error timeout;
add_header X-Cache-Status $upstream_cache_status;
    }

# 下单接口不缓存
location /order/create {
limit_req zone=order_limit burst=50 nodelay;
proxy_pass http://product_backend;
proxy_next_upstreamoff;  # 下单不重试
    }
}

# 订单接口限流: 每个IP每秒最多20个请求
limit_req_zone$binary_remote_addr zone=order_limit:10m rate=20r/s;

# 缓存配置
proxy_cache_path /data/nginx/cache/product
                 levels=1:2
                 keys_zone=product_cache:500m
                 max_size=50g
                 inactive=10m;

压测结果:

# 优化前
wrk -t8 -c2000 -d60s http://m.shop.com/product/12345
Requests/sec:   8,523.42
Latency: avg 234ms, p99 1.2s

# 优化后
Requests/sec:  52,341.18  (提升 6.1 倍)
Latency: avg 38ms, p99 156ms  (降低 85%)

◆ 案例二:微服务 API 网关

场景描述:作为微服务网关,需要高效转发数万后端服务请求,且支持灰度发布和流量染色。

Nginx 配置:

# 根据Cookie进行灰度发布
map$cookie_version$backend_pool {
    "beta" backend_beta;
default backend_stable;
}

upstream backend_stable {
server10.0.2.101:8080;
server10.0.2.102:8080;
keepalive256;
}

upstream backend_beta {
server10.0.2.201:8080;  # 灰度服务器
keepalive64;
}

server {
listen80;
server_name api.example.com;

location / {
# 动态选择后端池
proxy_pass http://$backend_pool;

# 长连接优化
proxy_http_version1.1;
proxy_set_header Connection "";

# 超时优化
proxy_connect_timeout5s;
proxy_read_timeout30s;

# 流量染色
add_header X-Backend-Pool $backend_pool;
    }
}

Tomcat 线程池配置:


<Executorname="apiThreadPool"
maxThreads="1000"
minSpareThreads="200"
prestartminSpareThreads="true" />

四、最佳实践和注意事项

4.1 最佳实践

◆ 4.1.1 性能优化

  • • 优化点一:静态资源分离
    # Nginx直接处理静态资源,不转发给Tomcat
    location~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
    root /data/static;
    expires30d;
    access_logoff;
    }

    效果:Nginx 处理静态文件的性能是 Tomcat 的 10 倍以上

  • • 优化点二:启用 HTTP/2
    server {
    listen443 ssl http2;  # 启用HTTP/2
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    }

    效果:多路复用,减少连接数,提升加载速度 30%~50%

  • • 优化点三:连接池复用
    upstream backend {
    server127.0.0.1:8080;
    keepalive256;  # 关键配置
    keepalive_requests10000;
    keepalive_timeout60s;
    }

    location / {
    proxy_pass http://backend;
    proxy_http_version1.1;  # 必须
    proxy_set_header Connection "";  # 必须
    }

    效果:减少 TCP 握手,QPS 提升 30%~40%

◆ 4.1.2 安全加固

  • • 安全措施一:限制请求速率
    # 全局限流
    limit_req_zone$binary_remote_addr zone=global_limit:10m rate=100r/s;
    limit_conn_zone$binary_remote_addr zone=conn_limit:10m;

    server {
    limit_req zone=global_limit burst=200 nodelay;
    limit_conn conn_limit 20;  # 单IP最多20个并发连接
    }
  • • 安全措施二:防止慢速攻击
    # Nginx配置
    client_body_timeout10s;
    client_header_timeout10s;
    send_timeout10s;

    # Tomcat配置
    <Connector connectionTimeout="20000"# 20秒超时
               connectionUploadTimeout="300000"# 上传文件5分钟超时
               disableUploadTimeout="false" />
  • • 安全措施三:隐藏版本信息
    
    
    
        
    # Nginx
    server_tokensoff;

    # Tomcat server.xml
    <Connector server="Apache" />  # 伪装成Apache

    # 或在web.xml中添加
    <error-page>
        <error-code>404error-code>
        /error/404.html
    error-page>

◆ 4.1.3 高可用配置

  • • Nginx 高可用:
    # 安装Keepalived实现主备
    yum install -y keepalived

    # /etc/keepalived/keepalived.conf
    vrrp_script check_nginx {
        script "/usr/local/bin/check_nginx.sh"
        interval 2
        weight -20
    }

    vrrp_instance VI_1 {
        state MASTER
        interface eth0
        virtual_router_id 51
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1234
        }
        virtual_ipaddress {
            192.168.1.200/24
        }
        track_script {
            check_nginx
        }
    }
  • • Tomcat 集群会话共享:

    <Context>
    <ValveclassName="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
    <ManagerclassName="com.orangefunction.tomcat.redissessions.RedisSessionManager"
    host="redis.example.com"
    port="6379"
    database="0"
    maxInactiveInterval="1800" />
    Context>

4.2 注意事项

◆ 4.2.1 配置注意事项

⚠️ 警告:参数调优需结合实际业务压测,避免盲目调大参数

  • • ❗ 注意事项一:线程数不是越大越好
    • • 错误示例:maxThreads="5000" 导致线程切换开销巨大
    • • 正确做法:从 200 开始,每次增加 100,压测找到最佳值
    • • 判断标准:CPU 使用率 70%~80%,响应时间稳定
  • • ❗ 注意事项二:Keep-Alive 超时时间需前后端一致
    • • 问题:Nginx keepalive_timeout > Tomcat keepAliveTimeout
    • • 后果:Nginx 认为连接还活着,但 Tomcat 已关闭,导致 502 错误
    • • 解决:Tomcat 超时时间应略大于 Nginx(如 Nginx 60s,Tomcat 65s)
  • • ❗ 注意事项三:压缩会增加 CPU 负载
    • •  场景:如果前端有 CDN 压缩,Nginx/Tomcat 可关闭压缩
    • • 建议:gzip_comp_level 设置 5~6 即可,不要设置 9

◆ 4.2.2 常见错误

错误现象
原因分析
解决方案
Nginx 502 Bad Gateway
后端 Tomcat 未启动或超时
检查 Tomcat 状态,调整 proxy_read_timeout
Too many open files
文件描述符限制过小
调整 ulimit 和 worker_rlimit_nofile
Tomcat 线程池耗尽
maxThreads
 过小或响应慢
增大线程池,优化慢接口
Connection reset by peer
Keep-Alive 超时不一致
统一前后端超时配置
Nginx 启动失败
端口被占用或配置语法错误
nginx -t
 检查配置,lsof -i:80 查端口
CPU 100%
线程数过多或死循环
jstack 查看线程栈,定位问题代码

◆ 4.2.3 兼容性问题

  • • 版本兼容:
    • • Tomcat 10+ 使用 Jakarta EE,旧应用需改 import 路径
    • • Nginx 1.15+ 支持 HTTP/2,但需 OpenSSL 1.0.2+
  • • 平台兼容:
    • • Windows 下 Nginx 性能差,仅适合开发环境
    • • Tomcat APR 模式需安装 Tomcat Native 库

五、故障排查和监控

5.1 故障排查

◆ 5.1.1 日志查看

# Nginx日志实时查看
tail -f /var/log/nginx/access.log | grep "502\|503\|504"

# Tomcat日志
tail -f /opt/tomcat/logs/catalina.out

# 分析响应时间慢的请求
awk '{if($NF>1000)print $0}' /var/log/nginx/access.log | tail  -20

◆ 5.1.2 常见问题排查

问题一:Nginx 502 错误

# 1. 检查Tomcat是否正常
curl -I http://127.0.0.1:8080

# 2. 查看Nginx错误日志
tail -f /var/log/nginx/error.log
# 常见原因: connect() failed (111: Connection refused)

# 3. 检查防火墙
iptables -L -n | grep 8080

# 4. 检查SELinux
getenforce
# 如果是Enforcing,临时关闭: setenforce 0

问题二:连接数打满

# 查看当前连接数
ss -ant | grep :80 | wc -l

# 查看各状态连接数
ss -ant | awk '{print $1}' | sort | uniq -c

# 查看Tomcat线程状态
curl http://localhost:8080/manager/status/all | grep "currentThreadsBusy"

# 解决方案:
# 1. 增大 maxThreads 和 maxConnections
# 2. 优化慢接口,减少响应时间
# 3. 启用连接池复用

问题三:内存泄露导致频繁 Full GC

# 查看GC情况
jstat -gcutil 1000

# 生成堆转储
jmap -dump:live,format=b,file=/tmp/heap.hprof

# 使用MAT分析(参考本系列第1篇文章)

◆ 5.1.3 性能分析

# Nginx性能指标
curl http://localhost/nginx_status
# 输出:
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

# Tomcat线程池监控
curl -u admin:password http://localhost:8080/manager/status?XML=true | grep threadInfo

# 系统负载
top -p $(pgrep -f tomcat)
iostat -x 1 10

5.2 性能监控

◆ 5.2.1 Prometheus + Grafana 监控

# prometheus.yml
scrape_configs:
# Nginx监控
-job_name:'nginx'
static_configs:
-targets: ['localhost:9113']  # nginx-prometheus-exporter

# Tomcat JMX监控
-job_name:'tomcat'
static_configs:
-targets: ['localhost:9404']  # jmx_exporter
# 部署nginx-prometheus-exporter
docker run -d -p 9113:9113 \
  nginx/nginx-prometheus-exporter:latest \
  -nginx.scrape-uri=http://nginx:80/nginx_status

# 部署jmx_exporter
java -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent-0.19.0.jar=9404:/opt/jmx_exporter/config.yml \
     -jar /opt/tomcat/bin/bootstrap.jar

◆ 5.2.2 告警规则

# prometheus_rules.yml
groups:
-name:nginx_alerts
rules:
-alert:NginxHighConnections
expr:nginx_connections_active>5000
for:5m
labels:
severity:warning
annotations:
summary:"Nginx连接数过高"
description:"当前连接数: {{ $value }}"

-alert:Nginx5xxErrors
expr:rate(nginx_http_requests_total{status=~"5.."}[5m])>10
for:2m
labels:
severity:critical
annotations:
summary:"Nginx 5xx错误率过高"

-name:tomcat_alerts
rules:
-alert:TomcatThreadPoolExhausted
expr:tomcat_threads_busy/tomcat_threads_max>0.9
for:5m
labels:
severity:critical
annotations:
summary:"Tomcat线程池即将耗尽"

-alert:TomcatHighHeapUsage
expr:jvm_memory_bytes_used{area="heap"}/jvm_memory_bytes_max{area="heap"}>0.85
for:10m
labels:
severity:warning
annotations:
summary:"Tomcat堆内存使用率过高"

◆ 5.2.3 自定义监控脚本

#!/bin/bash
# monitor_web_stack.sh
# 全栈监控脚本

NGINX_STATUS="http://localhost/nginx_status"
TOMCAT_STATUS="http://localhost:8080/manager/status"
ALERT_WEBHOOK="https://your-alert-system.com/webhook"

whiletruedo
# Nginx监控
    NGINX_CONN=$(curl -s $NGINX_STATUS | grep "Active" | awk '{print $3}')
if [ "$NGINX_CONN" -gt 5000 ]; then
        curl -X POST $ALERT_WEBHOOK -d "Nginx连接数过高: $NGINX_CONN"
fi

# Tomcat监控
    TOMCAT_PID=$(pgrep -f tomcat)
if [ -n "$TOMCAT_PID" ]; then
# JVM堆内存使用率
        HEAP_USAGE=$(jstat -gc $TOMCAT_PID | tail -1 | awk '{used=$3+$4+$6+$8; total=$1+$2+$5+$7; print int(used/total*100)}')
if [ "$HEAP_USAGE" -gt 85 ]; then
            curl -X POST $ALERT_WEBHOOK -d "Tomcat堆内存使用率: ${HEAP_USAGE}%"
fi

# Full GC次数
        FGC_COUNT=$(jstat -gcutil $TOMCAT_PID 1000 1 | tail -1 | awk '{print $14}')
# 记录到文件,下次对比增量
fi

sleep 60
done

5.3 备份与恢复

◆ 5.3.1 配置备份

#!/bin/bash
# backup_config.sh
BACKUP_DIR="/backup/web_config"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# 备份Nginx配置
tar -czf $BACKUP_DIR/nginx_conf_$DATE.tar.gz /etc/nginx

# 备份Tomcat配置
tar -czf $BACKUP_DIR/tomcat_conf_$DATE.tar.gz \
    /opt/tomcat/conf \
    /opt/tomcat/bin/setenv.sh

# 保留最近30天的备份
find $BACKUP_DIR -name "*.tar.gz"  -mtime +30 -delete

◆ 5.3.2 快速回滚

#!/bin/bash
# rollback.sh
# 快速回滚到上一个版本配置

BACKUP_DIR="/backup/web_config"
LATEST_NGINX=$(ls -t $BACKUP_DIR/nginx_conf_*.tar.gz | head -1)
LATEST_TOMCAT=$(ls -t $BACKUP_DIR/tomcat_conf_*.tar.gz | head -1)

# 停止服务
systemctl stop nginx
/opt/tomcat/bin/shutdown.sh

# 恢复配置
tar -xzf $LATEST_NGINX -C /
tar -xzf $LATEST_TOMCAT -C /

# 重启服务
systemctl start nginx
/opt/tomcat/bin/startup.sh

echo"配置已回滚至: $LATEST_NGINX$LATEST_TOMCAT"

六、总结

6.1 技术要点回顾

  • • ✅ 要点一:Tomcat 调优核心在于线程池配置、JVM 参数和连接器优化,需结合实际 QPS 和响应时间计算合理的 maxThreads
  • • ✅ 要点二:Nginx 调优重点是 worker_connections、keepalive 连接池、gzip 压缩和缓存策略,静态资源分离可显著提升性能
  • • ✅ 要点三:系统内核参数(ulimit、tcp_tw_reuse 等)是性能瓶颈的隐形杀手,必须同步优化
  • • ✅ 要点四:建立完善的监控体系(Prometheus + Grafana)和压测流程,持续优化才能保证长期稳定

6.2 进阶学习方向

  1. 1. Tengine/OpenResty:
  • • 学习资源:OpenResty 最佳实践
  • • 实践建议:使用 Lua 脚本实现动态路由、灰度发布等高级功能
  • 2. Tomcat 源码分析:
    • • 学习资源:《深入剖析Tomcat》
    • • 实践建议:理解 Connector、Processor、Adapter 的工作原理
  • 3. 全链路性能优化:
    • • 学习资源:《性能之巅》
    • • 实践建议:从网络、磁盘 I/O、数据库到应用代码的全栈优化

    6.3 参考资料

    • • Apache Tomcat 官方文档 - 权威配置说明
    • • Nginx 官方文档 - 完整参数手册
    • • 阿里云性能优化最佳实践 - 大厂实战经验
    • • Awesome Nginx - 精选资源合集

    附录

    A. 命令速查表

    # Nginx操作
    nginx -t                          # 检查配置语法
    nginx -s reload                   # 热重载配置
    nginx -V                          # 查看编译参数
    systemctl status nginx            # 查看服务状态

    # Tomcat操作
    /opt/tomcat/bin/startup.sh        # 启动
    /opt/tomcat/bin/shutdown.sh       # 停止
    tail -f logs/catalina.out         # 查看日志
    jps -lvm                          # 查看Java进程

    # 性能测试
    wrk -t8 -c1000 -d60s --latency http://example.com/
    ab -n 10000 -c 100 http://example.com/

    # 监控命令
    curl http://localhost/nginx_status  # Nginx状态
    jstat -gcutil 1000           # JVM GC统计
    top -H -p                    # 线程级CPU监控
    ss -s                              # 网络连接统计

    B. 参数速查表

    参数类别
    Nginx 关键参数
    Tomcat 关键参数
    推荐值
    并发连接
    worker_connections
    maxConnections
    10000
    工作线程
    worker_processes
    maxThreads
    auto/800
    长连接超时
    keepalive_timeout
    keepAliveTimeout
    60s
    连接池
    keepalive
    -
    256
    请求体大小限制
    client_max_body_size
    maxPostSize
    100m
    连接超时
    proxy_connect_timeout
    connectionTimeout
    10s/20s
    读取超时
    proxy_read_timeout
    -
    60s

    C. 故障排查 Checklist

    • • [ ] 检查服务状态:systemctl status nginx/tomcat
    • • [ ] 查看错误日志:tail -f error.log
    • • [ ] 检查端口监听:ss -tlnp | grep :80
    • • [ ] 测试后端连通性:curl -I http://localhost:8080
    • • [ ] 查看系统资源:top free -hdf -h
    • • [ ] 检查文件描述符:ulimit -n
    • • [ ] 查看网络连接:ss -snetstat -an | grep TIME_WAIT | wc -l
    • • [ ] JVM 内存检查:jstat -gcutil
    • • [ ] 线程池状态:访问 Tomcat Manager 查看
    • • [ ] 压测验证:wrk 或 ab 模拟高并发

    文末福利


    网络监控是保障网络系统和数据安全的重要手段,能够帮助运维人员及时发现并应对各种问题,及时发现并解决,从而确保网络的顺畅运行。

    谢谢一路支持,给大家分享6款开源免费的网络监控工具,并准备了对应的资料文档,建议运维工程师收藏(文末一键领取)。

    图片
    备注: 【监控合集】

    图片

    100%免费领取


    一、zabbix

    图片
    图片

    二、Prometheus


    图片

    内容较多,6款常用网络监控工具(zabbix、Prometheus、Cacti、Grafana、OpenNMS、Nagios不再一一介绍, 需要的朋友扫码备注【监控合集】,即可100%免费领取。

    图片

     以上所有资料获取请扫码

    备注:【监控合集】

    图片

    100%免费领取

    (后台不再回复,扫码一键领取)


    Python社区是高质量的Python/Django开发社区
    本文地址:http://www.python88.com/topic/189739