nginx+tomcat负载均衡群集

核心原理:

  1. Nginx: 作为反向代理服务器负载均衡器。它接收所有来自客户端的 HTTP/HTTPS 请求。

  2. Tomcat 集群: 部署多个相同的 Tomcat 实例(称为节点或服务器),运行同一个Web应用。

  3. 负载分发: Nginx 根据配置的负载均衡算法(如轮询、权重、最少连接、IP哈希等)将请求转发到后端的某一个 Tomcat 实例上。

  4. 高可用: 如果某个 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_certificatessl_certificate_key 指令指向你的证书和私钥文件。

    • 通常建议在 Nginx 端终止 SSL,然后以 HTTP 协议与后端的 Tomcat 通信(性能更好)。确保 proxy_set_header X-Forwarded-Proto $scheme; 配置正确,这样 Tomcat 应用才能知道原始请求是 HTTPS。

4. 测试与验证

  1. 检查配置: 运行 sudo nginx -t 检查 Nginx 配置语法是否正确。

  2. 重载 Nginx: 运行 sudo systemctl reload nginxsudo nginx -s reload 应用新配置。

  3. 访问测试: 使用浏览器或 curl 访问 Nginx 的 IP 地址或域名 (http://nginx_server_ip_or_domain)。应该能看到你的应用。

  4. 负载均衡验证:

    • 反复刷新浏览器或使用工具(如 ab, siege, wrk)发送大量请求。

    • 检查各个 Tomcat 实例的访问日志 (logs/localhost_access_log.<date>.txt) 或应用日志,观察请求是否被均匀(或按权重)分发到不同的节点。

  5. Session 测试:

    • 登录应用(触发 Session 创建)。

    • 检查 Session Cookie(通常是 JSESSIONID)。

    • 如果使用 ip_hash,尝试从不同客户端 IP 访问,观察 Session 是否跟随 IP 走。

    • 如果使用 Session 复制或 Redis,尝试停掉一个正在活跃服务的 Tomcat 节点(模拟故障),然后继续操作应用,检查 Session 是否还在(没有要求重新登录或丢失数据)。

  6. 故障转移测试:

    • 手动停止一个 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 复制)也需要开放相应端口。

相关推荐
棉花糖超人38 分钟前
【从0-1的HTML】第2篇:HTML标签
前端·html
exploration-earth1 小时前
本地优先的状态管理与工具选型策略
开发语言·前端·javascript
OpenTiny社区1 小时前
开源之夏报名倒计时3天!还有9个前端任务有余位,快来申请吧~
前端·github
ak啊1 小时前
WebGL魔法:从立方体到逼真阴影的奇妙之旅
前端·webgl
hang_bro1 小时前
使用js方法实现阻止按钮的默认点击事件&触发默认事件
前端·react.js·html
用户90738703648641 小时前
pnpm是如何解决幻影依赖的?
前端
树上有只程序猿2 小时前
Claude 4提升码农生产力的5种高级方式
前端
傻球2 小时前
没想到干前端2年了还能用上高中物理运动学知识
前端·react.js·开源
咚咚咚ddd2 小时前
前端组件:pc端通用新手引导组件最佳实践(React)
前端·react.js
Lazy_zheng2 小时前
🚀 前端开发福音:用 json-server 快速搭建本地 Mock 数据服务
前端·javascript·vue.js