使用 Nginx 实现 Tomcat 集群的负载均衡

整个过程可以分为以下几个核心步骤:

  1. 环境准备:准备好 Nginx 和多个 Tomcat 实例。
  2. 配置 Tomcat 集群 :确保所有 Tomcat 实例配置一致,并能通过 session 共享来维持用户登录状态。
  3. 配置 Nginx 负载均衡:设置 Nginx 反向代理,将请求分发到不同的 Tomcat 实例。
  4. 验证与测试:验证集群是否正常工作。

1. 环境准备

  • 一台 Nginx 服务器:用于接收外部请求并分发。
  • 两台或多台 Tomcat 服务器 :构成应用服务器集群。为了简单演示,我们可以在同一台服务器上启动多个 Tomcat 实例,通过修改端口来区分它们。

示例场景:

  • Nginx 服务器 :192.168.1.100,监听 80 端口。
  • Tomcat 集群 :
    • Tomcat 1: 监听 8080 端口
    • Tomcat 2: 监听 8081 端口

2. 配置 Tomcat 集群 (Session 共享)

这是集群部署的关键。如果不配置 Session 共享,用户的一次请求可能分发到 Tomcat 1,登录成功后,下一次请求可能分发到 Tomcat 2,而 Tomcat 2 上没有该用户的 Session,导致用户需要重新登录。

解决方案:使用 Redis 集中存储 Session。

步骤 A:修改 Tomcat 配置 (conf/context.xml)

在所有 Tomcat 实例的 conf/context.xml 文件中,添加以下 <Manager> 配置。

xml

复制代码
<!-- Tomcat 1 和 Tomcat 2 的 context.xml 都需要添加此配置 -->
<Context>
    ... 其他配置 ...

    <!-- 
        使用 Redis 存储 Session
        确保你的项目中已经引入了 tomcat-redis-session-manager 的相关 JAR 包
        下载地址: https://github.com/ran-jit/tomcat-redis-session-manager/releases
        需要将 tomcat-redis-session-manager-VERSION.jar, jedis-VERSION.jar, commons-pool2-VERSION.jar 放入 Tomcat 的 lib 目录
    -->
    <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
             host="127.0.0.1"          <!-- Redis 服务器地址 -->
             port="6379"               <!-- Redis 端口 -->
             password=""               <!-- Redis 密码 (如果没有则为空) -->
             database="0"              <!-- 使用的 Redis 数据库 -->
             maxInactiveInterval="60"  <!-- Session 过期时间(秒) -->
             sessionPersistPolicies="PERSIST_POLICY_1,PERSIST_POLICY_2" />

</Context>

重要:

  • 我的测试版本:apache-tomcat-9.0.113,下载JAR 包 jackson-databind-2.13.4.jar,redisson-all-3.17.0.jar,redisson-tomcat-9-3.17.0.jar,slf4j-simple-1.7.36.jar,放入每个 Tomcat 实例的 lib 目录下。
  • mven仓库地址:https://mvnrepository.com/artifact/com.dotcms
  • 所有 Tomcat 实例都必须连接到同一个 Redis 实例。
步骤 B:修改 Tomcat 端口 (如果在同一台服务器)

如果你的多个 Tomcat 实例在同一台服务器上,需要修改 conf/server.xml 文件来避免端口冲突。

对于 Tomcat 2 (tomcat2),修改以下三个端口:

xml

复制代码
<!-- 修改前 -->
<Server port="8005" shutdown="SHUTDOWN">
<Connector port="8080" protocol="HTTP/1.1" ... />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<!-- 修改后 (例如) -->
<Server port="8006" shutdown="SHUTDOWN">
<Connector port="8081" protocol="HTTP/1.1" ... />
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />
步骤 C:部署测试应用

为了验证负载均衡和 Session 共享是否生效,我们可以创建一个简单的 JSP 页面。

在两个 Tomcat 的 webapps/ROOT 目录下创建一个 index.jsp 文件:

jsp

复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Tomcat Cluster Test</title>
</head>
<body>
    <h1>Tomcat Cluster Test</h1>
    <p>服务器信息: <%= request.getLocalAddr() + ":" + request.getLocalPort() %></p>
    <p>Session ID: <%= session.getId() %></p>
    <p>Session 创建时间: <%= new java.util.Date(session.getCreationTime()) %></p>
    <%
        // 在 Session 中设置一个属性
        String dataName = "testData";
        if (session.getAttribute(dataName) == null) {
            session.setAttribute(dataName, "This is a test data from Tomcat.");
            out.println("<p>Session 数据已创建!</p>");
        } else {
            out.println("<p>Session 数据: " + session.getAttribute(dataName) + "</p>");
        }
    %>
</body>
</html>

启动 Tomcat:分别启动两个 Tomcat 实例。


3. 配置 Nginx 负载均衡

配置 Nginx,让它作为前端反向代理。

编辑 Nginx 的主配置文件 nginx.conf 或者在 conf.d 目录下创建一个新的配置文件(例如 tomcat-cluster.conf)。

nginx

复制代码
# 定义一个上游服务器组,即你的 Tomcat 集群
upstream tomcat_cluster {
    # 策略1: 默认轮询 (Round Robin)
    # 每个请求按时间顺序逐一分配到不同的后端服务器。
    server 127.0.0.1:8080 weight=1; # Tomcat 1
    server 127.0.0.1:8081 weight=1; # Tomcat 2

    # 策略2: 最少连接 (Least Connections)
    # 请求被转发到当前活动连接数最少的后端服务器。
    # least_conn;

    # 策略3: IP 哈希 (IP Hash)
    # 根据访问 IP 的哈希结果分配,确保来自同一 IP 的请求始终定向到同一台后端服务器。
    # ip_hash; 
}

# 配置一个 server 块来接收外部请求
server {
    listen 80;
    server_name 192.168.1.100; # 你的 Nginx 服务器地址或域名

    location / {
        # 将请求代理到上游服务器组
        proxy_pass http://tomcat_cluster;

        # 以下是一些推荐的 proxy 设置
        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;
        
        # 为了 WebSocket 支持 (如果需要)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # 配置静态资源直接由 Nginx 处理,提高性能
    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
        # 假设你的静态资源在 Nginx 的 html 目录下
        root /usr/share/nginx/html; 
        expires 30d; # 缓存30天
    }
}

配置说明:

  • upstream tomcat_cluster: 定义了一个名为 tomcat_cluster 的服务器池。
  • server 127.0.0.1:8080;: 指定了后端服务器的地址和端口。weight 参数表示权重,权重越高的服务器被分配到请求的概率越大。
  • proxy_pass http://tomcat_cluster;: 这是核心指令,它将当前 location 匹配的所有请求转发到 tomcat_cluster 这个服务器池中。
  • proxy_set_header: 设置一些重要的 HTTP Header,以便后端 Tomcat 能够获取到真实的客户端信息。

检查并重新加载 Nginx 配置:

运行

复制代码
# 检查配置语法是否正确
sudo nginx -t

# 如果语法正确,重新加载配置
sudo nginx -s reload

4. 验证与测试

现在,所有配置都已完成。打开你的浏览器,访问 Nginx 的地址:http://192.168.1.100。

预期结果:

  1. 负载均衡验证:

    • 第一次刷新页面,你可能会看到 "服务器信息" 显示 127.0.0.1:8080。
    • 第二次刷新页面,你可能会看到 "服务器信息" 显示 127.0.0.1:8081。
    • 这证明了 Nginx 正在将请求轮流分发到两个 Tomcat 实例上。
  2. Session 共享验证:

    • 在多次刷新页面,切换不同 Tomcat 服务器的过程中,你会发现 "Session ID" 始终是同一个。
    • "Session 数据" 也会一直显示,不会因为切换服务器而丢失。
    • 这证明了两个 Tomcat 实例成功地从 Redis 中共享了 Session 信息。
相关推荐
Joy T8 小时前
从 Nginx 到 Gateway 再到微服务:一次 AI 请求的完整链路
nginx·微服务·gateway·controller·路由转发·ai service·接口错误排查
小匠石钧知9 小时前
07_在k8s集群中安装ingress-nginx
nginx·容器·kubernetes·ingress
螺蛳粉 螺蛳粉10 小时前
第五篇:Keepalived + LVS 四层负载均衡高可用实战:DR 模式全流程
运维·负载均衡·lvs·keepalived·高可用
百度一下吧20 小时前
Nginx 使用手册:从安装配置到实战部署
运维·nginx
JAVA面经实录9171 天前
Java高级后端 · 全套面试通关手册(Nginx)
java·nginx·面试
积流成海1 天前
一致性哈希原理与实现:分布式系统负载均衡
算法·负载均衡·哈希算法·哈希函数·盘子工具站
lpfasd1233 天前
WinSW在Win7上失败真相-实测与修复
windows·nginx
一条大祥脚3 天前
【CS336】lecture4 MoE|负载均衡|MoE并行|训练稳定性|Deepseek回顾
运维·负载均衡
lpfasd1233 天前
nginx服务化五套方案原理解剖与选型
运维·nginx
IanSkunk3 天前
从检查设备到训练方案:眼科与视光中心设备联动的数据通路、字段口径与校验规则
服务器·数据库·负载均衡