使用 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 信息。
相关推荐
jiayong237 小时前
Tomcat性能优化面试题
java·性能优化·tomcat
连续讨伐16 小时前
前期小随笔
服务器·网络·nginx
jiayong2319 小时前
Tomcat架构与核心组件面试题
java·架构·tomcat
jiayong2319 小时前
Tomcat连接器与协议处理面试题
java·tomcat
不染尘.2 天前
Linux的rpm与yum
linux·mysql·jdk·centos·tomcat·ssh
计算机毕设指导62 天前
基于微信小程序的运动场馆服务系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
s_daqing2 天前
ubuntu(arm)使用nginx安装静态服务器
服务器·nginx·ubuntu
物有本木2 天前
httpsok-v2.0.8发布-支持IIS证书自动续签
nginx·ssl
Volunteer Technology2 天前
Nginx部署静态项目
运维·服务器·nginx
摇滚侠2 天前
尚硅谷 Nginx 教程(亿级流量 Nginx 架构设计),基本使用,笔记 6-42
java·笔记·nginx