核心原理:
nginx: 作为反向代理服务器和负载均衡器。它接收所有来自客户端的 http/https 请求。
tomcat 集群: 部署多个相同的 tomcat 实例(称为节点或服务器),运行同一个web应用。
负载分发: nginx 根据配置的负载均衡算法(如轮询、权重、最少连接、ip哈希等)将请求转发到后端的某一个 tomcat 实例上。
高可用: 如果某个 tomcat 实例宕机,nginx 能检测到并将其从可用服务器列表中剔除,将后续请求只发送给健康的实例,保证服务不中断。
部署步骤:
1. 准备环境
服务器: 至少需要两台服务器(物理机或虚拟机)。
nginx server (lb): 1台,用于运行 nginx 作为负载均衡器。
tomcat servers (app): 至少2台,用于运行 tomcat 应用服务器。建议使用相同的配置和操作系统。
软件:
nginx server: 安装 nginx。
tomcat servers: 安装 jdk 和相同版本的 tomcat。
网络: 确保所有服务器之间网络互通(nginx 能访问所有 tomcat 服务器的 tomcat 端口,通常 8080)。
应用: 将你的 web 应用(war 文件)部署到所有 tomcat 实例的
webapps目录下,确保应用状态一致。
2. 配置 tomcat 服务器
基本配置: 在每个 tomcat 服务器的
conf/server.xml中,确保<host>配置正确指向你的应用。关闭 ajp (可选但推荐): 如果你只使用 nginx 通过 http 代理 tomcat,可以注释掉或移除
conf/server.xml中默认的 ajp 1.3 连接器 (<connector port="8009" protocol="ajp/1.3" ...>)。nginx 通常使用 http 与 tomcat 通信。配置 http 连接器: 确保 http 连接器 (
<connector port="8080" protocol="http/1.1" ...>) 是启用的,并监听合适的端口(如 8080)和地址(通常是0.0.0.0或具体 ip)。session 管理 (关键!): 这是集群中最重要也是最复杂的一点。默认情况下,session 存储在单个 tomcat 的内存中。当用户请求被分发到不同节点时,后续请求如果落到另一个节点,会导致 session 丢失(用户需要重新登录等)。解决方案有:
a. session 粘滞 (sticky session):
在 nginx 配置中使用
ip_hash指令(基于客户端 ip)或hash $cookie_<jsessionid_cookie_name>(基于 session cookie)。优点:简单易配置,性能好(session 不需要复制)。
缺点:不是真正的高可用(如果用户“粘”住的那个 tomcat 宕机,该用户的 session 丢失);负载可能不够均衡(某些 ip 请求量大)。
b. session 复制 (tomcat clustering):
配置 tomcat 集群,让节点间自动复制 session 数据。
修改
conf/server.xml,取消注释<cluster>部分,并配置receiver(地址/端口) 和membership(组播地址/端口)。在应用的
web-inf/web.xml中添加<distributable/>标签。确保应用中的所有放入 session 的对象都实现了
java.io.serializable接口。优点:真正的高可用,请求可以发送到任意节点。
缺点:配置复杂;网络开销大(频繁复制 session 数据);节点越多复制性能影响越大;存在复制延迟风险。
c. 集中式 session 存储:
将 session 数据存储在外部共享存储中,如 redis、memcached、数据库。
使用 tomcat 的 session manager 实现(如
redissessionmanager)。优点:彻底解耦 session 和 tomcat 节点;高可用性好;扩展性强。
缺点:引入外部依赖(redis/memcached/db)的运维复杂性和潜在单点;网络访问比本地内存慢。
选择建议: 对于中小型应用或对 session 丢失容忍度稍高的场景,
ip_hash是简单有效的选择。对高可用要求严格或大型应用,推荐使用 redis 集中存储 session。
3. 配置 nginx 负载均衡
编辑 nginx 配置文件: 通常是 /etc/nginx/nginx.conf 或 /etc/nginx/conf.d/default.conf 或创建一个新的文件如 /etc/nginx/conf.d/load-balancer.conf。
配置 upstream 块: 定义一个后端 tomcat 服务器池。
http {
upstream tomcat_cluster {
# 负载均衡算法 (可选: 默认是轮询 round-robin)
# least_conn; # 最少连接数
# ip_hash; # 基于客户端ip的session粘滞
# hash $cookie_<jsessionid_cookie_name> consistent; # 基于session cookie的粘滞
# 定义后端tomcat服务器列表
# 格式: server <tomcat_server_ip>:<tomcat_port> [weight=数值] [max_fails=数值] [fail_timeout=时间];
server 192.168.1.101:8080 weight=2 max_fails=3 fail_timeout=30s; # tomcat 节点1, 权重2
server 192.168.1.102:8080 weight=1 max_fails=3 fail_timeout=30s; # tomcat 节点2, 权重1
server 192.168.1.103:8080 backup; # 备用节点,只有当主节点都不可用时才启用
}
...
}server: 指定 tomcat 实例的 ip 和端口。weight: 权重,数值越大被分配到的请求越多。用于处理性能不同的服务器。max_fails: 在fail_timeout时间内,允许失败的次数。超过后认为该节点不可用。fail_timeout: 节点被标记为不可用的时间长度,以及检查失败的时间窗口。backup: 标记为备份服务器。只有当所有非 backup 服务器都不可用时,才会启用 backup 服务器。
配置 server 块: 设置 nginx 监听端口,并将请求代理到 upstream 池。
server {
listen 80; # nginx监听的端口 (通常是80或443)
server_name yourdomain.com www.yourdomain.com; # 你的域名或服务器ip
location / {
# 将请求代理到上面定义的upstream池 'tomcat_cluster'
proxy_pass http://tomcat_cluster;
# 重要的代理设置 (通常需要添加)
proxy_set_header host $host; # 传递原始请求的主机头
proxy_set_header x-real-ip $remote_addr; # 传递客户端真实ip
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; # 传递代理链ip
proxy_set_header x-forwarded-proto $scheme; # 传递原始协议 (http/https)
# 连接超时设置 (根据需要调整)
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 如果使用基于cookie的session粘滞,确保传递session cookie
proxy_cookie_path / /;
# 或者更精确地处理jsessionid路径 (根据你的应用配置)
# proxy_cookie_path ~*^/.* /;
}
# 可选: 配置静态文件由nginx直接处理,减轻tomcat压力
location ~* \.(jpg|jpeg|png|gif|ico|css|js|html|txt|woff|woff2|ttf|svg)$ {
root /path/to/your/static/files; # 静态文件存放的本地路径
expires 30d; # 设置浏览器缓存过期时间
access_log off; # 可选:关闭静态文件访问日志
}
# 可选: 错误页面重定向
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}https (强烈推荐):
在 nginx 上配置 ssl/tls 证书。
修改
server块中的listen指令为listen 443 ssl;。添加
ssl_certificate和ssl_certificate_key指令指向你的证书和私钥文件。通常建议在 nginx 端终止 ssl,然后以 http 协议与后端的 tomcat 通信(性能更好)。确保
proxy_set_header x-forwarded-proto $scheme;配置正确,这样 tomcat 应用才能知道原始请求是 https。
4. 测试与验证
检查配置: 运行
sudo nginx -t检查 nginx 配置语法是否正确。重载 nginx: 运行
sudo systemctl reload nginx或sudo nginx -s reload应用新配置。访问测试: 使用浏览器或
curl访问 nginx 的 ip 地址或域名 (http://nginx_server_ip_or_domain)。应该能看到你的应用。负载均衡验证:
反复刷新浏览器或使用工具(如
ab,siege,wrk)发送大量请求。检查各个 tomcat 实例的访问日志 (
logs/localhost_access_log.<date>.txt) 或应用日志,观察请求是否被均匀(或按权重)分发到不同的节点。
session 测试:
登录应用(触发 session 创建)。
检查 session cookie(通常是
jsessionid)。如果使用
ip_hash,尝试从不同客户端 ip 访问,观察 session 是否跟随 ip 走。如果使用 session 复制或 redis,尝试停掉一个正在活跃服务的 tomcat 节点(模拟故障),然后继续操作应用,检查 session 是否还在(没有要求重新登录或丢失数据)。
故障转移测试:
手动停止一个 tomcat 实例 (
./bin/shutdown.sh)。继续访问应用。nginx 应该很快(在
fail_timeout内)检测到该节点失败,并将后续请求只发送给健康的节点。观察 nginx 错误日志 (
/var/log/nginx/error.log) 是否有连接后端失败的信息。重新启动停掉的 tomcat 实例。nginx 应该能自动将其重新加入可用服务器池(根据健康检查机制)。
5. 监控与维护
监控:
nginx: 监控状态码 (5xx 错误)、连接数、请求速率、上游服务器状态 (
nginx_status模块或 prometheus + grafana)。tomcat: 监控 jvm 内存、gc 情况、线程池状态、请求处理时间 (jmx, tomcat manager, prometheus + jmx_exporter)。
系统: cpu、内存、磁盘 i/o、网络流量。
session 存储 (如用 redis): 监控 redis 状态、内存使用、连接数。
日志分析: 定期分析 nginx 访问日志、tomcat 访问日志和应用日志,发现问题。
滚动更新:
更新应用时,逐个将 tomcat 节点从 nginx upstream 中摘除 (
down标记或修改配置临时移除),更新应用,启动并验证,然后再将其加入集群,再处理下一个节点。使用更高级的蓝绿部署或金丝雀发布策略。
关键优势:
高可用性: 单点故障不影响整体服务。
可扩展性: 通过增加 tomcat 节点轻松应对流量增长。
性能提升: 分散请求到多个服务器,提高并发处理能力。
灵活性: nginx 可处理静态资源、ssl 卸载、缓存等,减轻 tomcat 负担。
常见问题与注意事项:
session 一致性: 这是集群的核心挑战,务必根据应用需求选择合适的方案并充分测试。
文件上传/共享存储: 如果应用涉及用户上传文件,需要确保所有 tomcat 节点都能访问到这些文件(使用共享存储如 nfs、glusterfs,或云存储,或在应用层处理文件同步)。
配置一致性: 确保所有 tomcat 节点上的应用配置、环境变量、依赖库版本等完全一致。
网络延迟: 确保 nginx 与 tomcat 节点之间,以及 tomcat 节点之间(如果使用 session 复制)的网络延迟足够低。
健康检查: nginx 的被动健康检查 (
max_fails/fail_timeout) 是基础。对于更精确的控制,可以考虑使用主动健康检查模块(如nginx_upstream_check_module或商业版 nginx plus)。防火墙: 确保 nginx 服务器的 80/443 端口开放,并且 nginx 能访问所有 tomcat 节点的指定端口(如 8080),tomcat 节点之间如果通信(session 复制)也需要开放相应端口。
总结
到此这篇关于nginx+tomcat负载均衡群集部署步骤的文章就介绍到这了,更多相关nginx+tomcat负载均衡群集内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论