Nginx 与 Tomcat 的协同配置,关键在于反向代理与负载均衡
Nginx 处理静态资源与高并发连接,Tomcat 负责动态业务逻辑与 Java 应用运行,两者通过反向代理无缝衔接,是生产环境中最稳健的 Java Web 架构之一,正确的配置不仅能提升系统吞吐量,还能实现负载均衡与故障转移,是每个运维和开发人员必须掌握的技能。
为什么需要 Nginx 搭配 Tomcat?
Tomcat 作为 Servlet 容器,擅长运行 Java 应用,但其对静态文件(图片、CSS、JS)的处理效率远低于 Nginx,且在高并发场景下,Tomcat 的线程模型容易成为瓶颈,Nginx 采用事件驱动架构,单进程可轻松支撑数万并发连接,同时具备反向代理、缓存、动静分离、灰度发布等高级能力。
核心价值点:
- 动静分离:让 Nginx 直接返回静态资源,Tomcat 只处理 JSP/Servlet 请求,大幅降低 Tomcat 压力。
- 负载均衡:Nginx 可将请求分发到多个 Tomcat 实例,实现水平扩展。
- 安全防护:隐藏 Tomcat 真实端口,拦截恶意请求,支持 SSL 终端。
基础反向代理配置
最简配置只需三步:定义 upstream 集群、配置 server 监听、设置 location 转发规则。
http {
upstream tomcat_cluster {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=2; # 权重越高,分配越多
# 支持多台 Tomcat 实例
}
server {
listen 80;
server_name example.com;
# 静态资源直接由 Nginx 处理
location ~ .(html|css|js|png|jpg|jpeg|gif|ico|svg)$ {
root /data/static;
expires 7d;
access_log off;
}
# 动态请求反向代理至 Tomcat
location / {
proxy_pass http://tomcat_cluster;
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;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
}
}
}
关键参数说明:
- proxy_pass 是核心指令,指向 upstream 定义的名称。
- proxy_set_header 必须传递真实 IP 和协议,否则 Tomcat 日志无法记录客户端真实地址,且 HTTPS 跳转会出错。
- 超时时间根据业务复杂度调整,长任务需适当调大。
负载均衡策略与会话保持
当应用需要水平扩展时,Nginx 支持多种负载均衡算法:
- 轮询(默认):每个请求按时间顺序轮流分配到后端。
- weight 权重:按服务器性能比例分配,适合异构服务器。
- ip_hash:根据客户端 IP 的 hash 结果固定分配,解决 session 问题(但可能造成负载不均)。
- least_conn:优先分配给当前连接数最少的 Tomcat,适合长连接场景。

关键问题:Session 一致性。 Tomcat 默认 session 存储在内存中,多实例下请求可能落到不同机器导致 session 丢失,解决方案:
- Nginx 层:使用
ip_hash,同一 IP 固定访问一台 Tomcat(简单但不均匀)。 - Tomcat 层:配置
jvmRoute与集群会话复制(对网络延迟敏感)。 - 应用层:将 session 存入 Redis,这是目前最推荐的方案。
专业建议: 优先选择 Redis 集中式 session,彻底摆脱前端负载均衡与后端会话的耦合,便于后续弹性伸缩。
动静分离优化与缓存策略
动静分离不仅能解放 Tomcat,还能借助 Nginx 强大的缓存能力提升响应速度。
静态资源缓存:
location ~ .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
}
如果静态资源存放在 Tomcat 的 webapps 中,可用 alias 或 root 指向对应目录,让 Nginx 直接读取文件系统,避免每次请求都转发给 Tomcat,对于需要更新的文件,建议文件名带哈希值(如 app.3f2b9.css),配合 immutable 实现永久缓存。
动态页面缓存: 对于不频繁变更的 API 响应,Nginx 可配置 proxy_cache 做本地缓存,极大减少 Tomcat 压力,但需谨慎设置缓存键和有效期,防止数据不一致。
HTTPS 终结与前向安全
在 Nginx 层配置 SSL 证书,证书续期与配置只需在 Nginx 操作,Tomcat 只需监听 HTTP 并信任代理即可,同时强制跳转 HTTPS:
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://tomcat_cluster;
# 确保传递给 Tomcat 的协议为 https
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Tomcat 的 server.xml 中需配置:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443"
proxyPort="443" />
Tomcat 的 remoteIpValve 可以识别代理头,自动修正客户端 IP,避免日志失真。
健康检查与故障转移
Nginx 默认不主动检查后端健康状态,只依赖请求失败重试,但生产环境中,必须配置主动健康检查(Nginx Plus 原生支持,开源版可用 nginx_upstream_check_module 模块或通过 max_fails 与 fail_timeout 实现被动检查)。
开源版推荐配置:
upstream tomcat_cluster {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
keepalive 32; # 开启连接复用,提升性能
}
max_fails=3 表示在 30 秒内如果失败 3 次,则该服务器被标记为不可用,30 秒后重新探测。注意:被动检查不能发现无响应的挂起连接,建议结合第三方健康检查模块或外部监控脚本。
酷番云实践案例
我们曾帮助一家电商客户做双十一大促前的架构优化,客户原有架构是 Nginx 单机反代单台 Tomcat,大促前预估流量增长 10 倍,Tomcat 成为瓶颈。
我们的解决方案(基于酷番云高性能云服务器):
- 动态扩容:在酷番云上创建两台 8 核 16G 的 Tomcat 节点,加入 upstream 集群,采用
least_conn策略,平衡长连接下载与普通请求。 - 静态资源全量上云:将图片、CSS、JS 迁移至酷番云对象存储,Nginx 通过反向代理至对象存储并缓存,Tomcat 彻底免于静态请求消耗。
- 配置 Nginx 缓存动态 API:针对商品详情页接口,开启
proxy_cache,缓存 10 秒,避免瞬间热点直接击穿数据库。 - 健康检查:利用酷番云负载均衡服务(含健康检查)与自建 Nginx
max_fails双重保障,某台 Tomcat 挂掉,请求自动转移到健康节点,业务无感知。
效果: 大促当天峰值 QPS 达到 8,200,Tomcat 平均负载稳定在 1.5 以下,全程零故障,重点在于酷番云弹性扩容能力让两台新增节点在 5 分钟内完成部署,且 Nginx 配置热加载实现无感上线。
常见配置误区与调优建议
- 忽略 keepalive 长连接:
与
proxy_http_version 1.1
upstream keepalive 32必须搭配使用,否则 Nginx 每次请求都新建 TCP 连接,性能损失巨大。 - 超时时间不合理:对于上传下载接口,
proxy_read_timeout若过短,会导致大文件传输中断;建议根据实际场景分开配置 location。 - 未开启 HTTP/2:如果网站已配置 HTTPS,务必开启
http2,多路复用可以显著减少请求延迟。 - worker_processes 与 worker_connections 调优:worker_processes 设为 CPU 核心数,worker_connections 根据内存和并发需求调整。
- 防火墙遗漏:Tomcat 端口(如 8080)只应对内网开放,绝不可暴露公网,否则绕过 Nginx 直达 Tomcat 会导致安全风险。
相关问答
问题1:Nginx 配置了 proxy_pass,但 Tomcat 中获取到的客户端 IP 是 127.0.0.1,怎么办?
解答: 这是因为 Nginx 转发请求时没有传递客户端 IP,请在 Nginx 的 location 中添加以下三行:
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
然后修改 Tomcat 的 server.xml 中 Connector,添加:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="127.0.0.1|::1"
remoteIpHeader="X-Forwarded-For"
proxiesHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto" />
重启 Tomcat 后,request.getRemoteAddr() 即可返回真实客户端 IP,注意 internalProxies 要设置为 Nginx 所在服务器的内网 IP,防止伪造。
问题2:如何平滑修改 Nginx 配置而不中断服务?
解答: 修改 Nginx 配置文件后,先执行 nginx -t 校验语法,确认无误后,使用 kill -HUP $(cat /var/run/nginx.pid) 或 nginx -s reload 进行热重载,Nginx 会启动新的 worker 进程,优雅地关闭旧进程,整个过程中没有请求丢失,若涉及 upstream 服务器变更,reload 同样生效,不会中断现有长连接,已建立的长连接继续由旧进程处理,新连接交给新进程,这是 Nginx 生产运维的标准操作。
互动引导: 你在 Nginx 配置 Tomcat 时是否遇到过什么奇怪的问题?session 丢失、上传超时或者 HTTPS 循环跳转?欢迎在评论区留言你的场景,我会第一时间为你分析排查思路,如果本文对你有帮助,别忘了点赞收藏,后续我会继续输出 Linux 运维与架构方面的实战干货。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/765341.html

