欢迎光临
我们一直在努力

Java 部署:Tomcat 集群部署(负载均衡 + 会话共享)

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Java部署这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • Java 部署:Tomcat 集群部署(负载均衡 + 会话共享) 🚀
    • 一、为什么需要 Tomcat 集群?🤔
    • 二、架构设计概览 🏗️
    • 三、环境准备 🛠️
      • 1. 软件版本要求
      • 2. 服务器规划(以 3 节点为例)
    • 四、部署 Tomcat 节点 🖥️
      • 1. 安装 Tomcat
      • 2. 配置 server.xml(关键!)
      • 3. 部署测试应用
    • 五、配置 Nginx 负载均衡 ⚖️
      • 1. 安装 Nginx
      • 2. 配置 upstream 和 proxy
      • 3. 重启 Nginx
    • 六、实现会话共享:Redis 方案 🧠
      • 1. 为什么选择 Redis?
      • 2. 安装并启动 Redis
      • 3. 集成 Tomcat 与 Redis
        • 步骤 1:下载依赖 JAR
        • 步骤 2:配置 context.xml
        • 步骤 3:重启 Tomcat
    • 七、验证集群功能 ✅
      • 1. 测试负载均衡
      • 2. 测试会话共享
      • 3. 查看 Redis 中的 Session
    • 八、Java 代码示例:自定义 Session 管理器 🧩
    • 九、高级配置与优化 🚀
      • 1. 会话粘性(Sticky Session) vs 无状态
      • 2. 健康检查
      • 3. SSL/TLS 终止
    • 十、常见问题排查 🛠️
      • 1. Session 未共享
      • 2. 负载不均
      • 3. Redis 连接泄漏
    • 十一、替代方案对比 📊
    • 十二、安全加固 🔒
    • 十三、总结 🎯
    • 附录:完整架构图 📐

Java 部署:Tomcat 集群部署(负载均衡 + 会话共享) 🚀

在现代 Web 应用开发中,单机部署 Tomcat 已经无法满足高并发、高可用的业务需求。为了提升系统稳定性、可扩展性和容错能力,Tomcat 集群部署成为企业级 Java 应用的标准实践。本文将深入探讨如何通过 负载均衡 + 会话共享 构建一个高可用的 Tomcat 集群,并提供完整的配置步骤与 Java 代码示例。


一、为什么需要 Tomcat 集群?🤔

单台 Tomcat 服务器存在以下瓶颈:

  • 性能瓶颈:单机 CPU、内存、网络带宽有限,难以应对高并发请求。
  • 单点故障:一旦服务器宕机,整个应用不可用。
  • 扩展性差:无法通过增加机器横向扩展服务能力。

而 Tomcat 集群通过以下机制解决上述问题:

✅ 负载均衡(Load Balancing):将用户请求分发到多个 Tomcat 实例,提升吞吐量。 ✅ 会话共享(Session Replication / Sharing):确保用户在不同节点间切换时,登录状态等会话信息不丢失。 ✅ 高可用(High Availability):单个节点故障不影响整体服务。

💡 提示:集群 ≠ 分布式。集群是同一应用的多个副本,分布式是将应用拆分为多个子系统。


二、架构设计概览 🏗️

一个典型的 Tomcat 集群架构如下:

#mermaid-svg-1fm8LW21R6N7cHNu{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1fm8LW21R6N7cHNu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1fm8LW21R6N7cHNu .error-icon{fill:#552222;}#mermaid-svg-1fm8LW21R6N7cHNu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1fm8LW21R6N7cHNu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1fm8LW21R6N7cHNu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1fm8LW21R6N7cHNu .marker.cross{stroke:#333333;}#mermaid-svg-1fm8LW21R6N7cHNu svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1fm8LW21R6N7cHNu p{margin:0;}#mermaid-svg-1fm8LW21R6N7cHNu .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1fm8LW21R6N7cHNu .cluster-label text{fill:#333;}#mermaid-svg-1fm8LW21R6N7cHNu .cluster-label span{color:#333;}#mermaid-svg-1fm8LW21R6N7cHNu .cluster-label span p{background-color:transparent;}#mermaid-svg-1fm8LW21R6N7cHNu .label text,#mermaid-svg-1fm8LW21R6N7cHNu span{fill:#333;color:#333;}#mermaid-svg-1fm8LW21R6N7cHNu .node rect,#mermaid-svg-1fm8LW21R6N7cHNu .node circle,#mermaid-svg-1fm8LW21R6N7cHNu .node ellipse,#mermaid-svg-1fm8LW21R6N7cHNu .node polygon,#mermaid-svg-1fm8LW21R6N7cHNu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1fm8LW21R6N7cHNu .rough-node .label text,#mermaid-svg-1fm8LW21R6N7cHNu .node .label text,#mermaid-svg-1fm8LW21R6N7cHNu .image-shape .label,#mermaid-svg-1fm8LW21R6N7cHNu .icon-shape .label{text-anchor:middle;}#mermaid-svg-1fm8LW21R6N7cHNu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1fm8LW21R6N7cHNu .rough-node .label,#mermaid-svg-1fm8LW21R6N7cHNu .node .label,#mermaid-svg-1fm8LW21R6N7cHNu .image-shape .label,#mermaid-svg-1fm8LW21R6N7cHNu .icon-shape .label{text-align:center;}#mermaid-svg-1fm8LW21R6N7cHNu .node.clickable{cursor:pointer;}#mermaid-svg-1fm8LW21R6N7cHNu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1fm8LW21R6N7cHNu .arrowheadPath{fill:#333333;}#mermaid-svg-1fm8LW21R6N7cHNu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1fm8LW21R6N7cHNu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1fm8LW21R6N7cHNu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1fm8LW21R6N7cHNu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1fm8LW21R6N7cHNu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1fm8LW21R6N7cHNu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1fm8LW21R6N7cHNu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1fm8LW21R6N7cHNu .cluster text{fill:#333;}#mermaid-svg-1fm8LW21R6N7cHNu .cluster span{color:#333;}#mermaid-svg-1fm8LW21R6N7cHNu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1fm8LW21R6N7cHNu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1fm8LW21R6N7cHNu rect.text{fill:none;stroke-width:0;}#mermaid-svg-1fm8LW21R6N7cHNu .icon-shape,#mermaid-svg-1fm8LW21R6N7cHNu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1fm8LW21R6N7cHNu .icon-shape p,#mermaid-svg-1fm8LW21R6N7cHNu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1fm8LW21R6N7cHNu .icon-shape rect,#mermaid-svg-1fm8LW21R6N7cHNu .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1fm8LW21R6N7cHNu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1fm8LW21R6N7cHNu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1fm8LW21R6N7cHNu :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Client

Nginx / Apache

Tomcat 1

Tomcat 2

Tomcat 3

Redis / MySQL / Memcached

  • 前端负载均衡器:Nginx 或 Apache HTTP Server,负责请求分发。
  • 后端 Tomcat 节点:多个运行相同 Web 应用的 Tomcat 实例。
  • 会话存储中心:Redis、MySQL 或 Memcached,用于集中存储 Session 数据。

🔗 Nginx 官方文档 提供了详细的负载均衡配置指南。


三、环境准备 🛠️

1. 软件版本要求

组件版本建议
Java JDK 8+(推荐 JDK 11 或 17)
Tomcat 9.x 或 10.x
Nginx 1.18+
Redis 6.x+(用于会话共享)

2. 服务器规划(以 3 节点为例)

主机名IP 地址角色
nginx-server 192.168.1.10 Nginx 负载均衡器
tomcat-node1 192.168.1.11 Tomcat 实例 1
tomcat-node2 192.168.1.12 Tomcat 实例 2
tomcat-node3 192.168.1.13 Tomcat 实例 3
redis-server 192.168.1.20 Redis 会话存储

⚠️ 所有服务器需关闭防火墙或开放对应端口(如 8080、6379、80 等)。


四、部署 Tomcat 节点 🖥️

1. 安装 Tomcat

在每台 Tomcat 节点上执行:

# 下载 Tomcat(以 9.0.85 为例)
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.85/bin/apache-tomcat-9.0.85.tar.gz
tar -zxvf apache-tomcat-9.0.85.tar.gz
mv apache-tomcat-9.0.85 /opt/tomcat

2. 配置 server.xml(关键!)

为每个节点设置唯一的 jvmRoute,用于会话粘性(Sticky Session):

tomcat-node1 的 conf/server.xml:

<Engine name="Catalina" defaultHost="localhost" jvmRoute="node1">

tomcat-node2:

<Engine name="Catalina" defaultHost="localhost" jvmRoute="node2">

tomcat-node3:

<Engine name="Catalina" defaultHost="localhost" jvmRoute="node3">

✅ jvmRoute 必须与 Nginx 中 upstream 的 server 名称一致。

3. 部署测试应用

创建一个简单的 Web 应用 cluster-demo.war,包含以下文件:

目录结构:

cluster-demo/
├── WEB-INF/
│ └── web.xml
└── index.jsp

web.xml(无需特殊配置):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

<display-name>Cluster Demo</display-name>
</web-app>

index.jsp(关键!用于测试会话和节点识别):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 获取当前会话ID
String sessionId = session.getId();
// 设置一个计数器,每次访问+1
Integer count = (Integer) session.getAttribute("visitCount");
if (count == null) count = 0;
count++;
session.setAttribute("visitCount", count);
%>
<html>
<head><title>Tomcat Cluster Test</title></head>
<body>
<h2>🎉 欢迎访问 Tomcat 集群!</h2>
<p>当前会话 ID: <strong><%= sessionId %></strong></p>
<p>您已访问本页面 <strong><%= count %></strong> 次。</p>
<p>当前处理节点: <strong>
<%
String jvmRoute = request.getServletContext().getServerInfo();
// 更准确的方式:通过 JSESSIONID 判断
String cookie = request.getHeader("Cookie");
if (cookie != null && cookie.contains("JSESSIONID")) {
String[] parts = cookie.split("JSESSIONID=");
if (parts.length > 1) {
String jsession = parts[1].split(";")[0];
if (jsession.contains(".node1")) out.print("Node 1 (192.168.1.11)");
else if (jsession.contains(".node2")) out.print("Node 2 (192.168.1.12)");
else if (jsession.contains(".node3")) out.print("Node 3 (192.168.1.13)");
else out.print("Unknown Node");
}
}
%>
</strong></p>
<br>
<a href="index.jsp">刷新页面</a>
</body>
</html>

将 cluster-demo.war 复制到所有 Tomcat 节点的 webapps/ 目录下。


五、配置 Nginx 负载均衡 ⚖️

在 nginx-server 上安装并配置 Nginx。

1. 安装 Nginx

# Ubuntu/Debian
sudo apt update && sudo apt install nginx

# CentOS/RHEL
sudo yum install nginx

2. 配置 upstream 和 proxy

编辑 /etc/nginx/sites-available/default 或新建配置文件:

upstream tomcat_cluster {
# 启用 sticky session(基于 cookie)
ip_hash; # 可选:基于 IP 的会话保持

# 或使用更灵活的 sticky cookie(需 nginx-plus 或第三方模块)
# sticky cookie srv_id expires=1h domain=.example.com path=/;

server 192.168.1.11:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.13:8080 weight=1 max_fails=2 fail_timeout=30s;
}

server {
listen 80;
server_name cluster.example.com;

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;

# 重要:传递 JSESSIONID cookie
proxy_cookie_path / "/; HTTPOnly; Secure";
}

# 健康检查(可选)
location /status {
access_log off;
allow 127.0.0.1;
deny all;
stub_status on;
}
}

🔗 Nginx 负载均衡官方指南 提供了更多策略(如 least_conn、hash 等)。

3. 重启 Nginx

sudo nginx -t # 测试配置
sudo systemctl reload nginx


六、实现会话共享:Redis 方案 🧠

默认情况下,Tomcat 的 Session 存储在内存中,集群环境下无法共享。我们需要将会话数据持久化到外部存储。

1. 为什么选择 Redis?

  • 高性能:内存数据库,读写极快。
  • 支持过期:自动清理过期 Session。
  • 成熟生态:有成熟的 Tomcat 插件支持。

🔗 Redis 官方文档 详细介绍了其数据结构和配置。

2. 安装并启动 Redis

在 redis-server 上:

# Ubuntu
sudo apt install redis-server
sudo systemctl start redis
sudo systemctl enable redis

编辑 /etc/redis/redis.conf,确保:

bind 0.0.0.0 # 允许远程连接
protected-mode no # 关闭保护模式(生产环境应设密码)
port 6379
timeout 0
tcp-keepalive 300

重启 Redis:

sudo systemctl restart redis

3. 集成 Tomcat 与 Redis

我们使用开源项目 Tomcat Redis Session Manager(简称 TRSM)。

步骤 1:下载依赖 JAR

将以下 JAR 文件放入每个 Tomcat 节点的 lib/ 目录:

  • tomcat-redis-session-manager-VERSION.jar
  • jedis-3.6.0.jar(Redis 客户端)
  • commons-pool2-2.11.1.jar(连接池)

💡 由于不能提供 GitHub 地址,建议通过 Maven Central 搜索 tomcat-redis-session-manager 获取最新版。

步骤 2:配置 context.xml

在每个 Tomcat 节点的 conf/context.xml 中添加:

<Context>
<!– 其他配置… –>

<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="192.168.1.20"
port="6379"
database="0"
maxInactiveInterval="1800"
sessionPersistPolicies="PERSIST_POLICY_DEFAULT"
sentinelMaster=""
sentinels=""
connectionTimeout="2000"
soTimeout="2000"
password=""
clientName="" />

</Context>

⚠️ 注意:className 必须与你使用的 JAR 包中的类路径一致。

步骤 3:重启 Tomcat

/opt/tomcat/bin/shutdown.sh
/opt/tomcat/bin/startup.sh


七、验证集群功能 ✅

1. 测试负载均衡

访问 http://192.168.1.10/cluster-demo/(Nginx 地址),多次刷新页面:

  • 如果使用 ip_hash,同一客户端始终访问同一节点。
  • 如果使用轮询(默认),节点会轮换。

观察页面显示的“当前处理节点”是否变化。

2. 测试会话共享

  • 在页面上看到“访问次数”为 1。
  • 刷新几次,次数递增。
  • 手动停止当前节点的 Tomcat(如 node1)。
  • 再次刷新,请求被转发到其他节点(如 node2)。
  • 关键:访问次数应继续递增,而非重置为 1!

这证明 Session 已成功共享。

3. 查看 Redis 中的 Session

在 Redis 服务器上执行:

redis-cli
KEYS *
GET "r:YOUR_SESSION_ID"

你会看到类似:

"\\xac\\xed\\x00\\x05sr\\x00Kcom.orangefunction.tomcat.redissessions.SessionSerializationMetadata…"

说明 Session 已序列化存储。


八、Java 代码示例:自定义 Session 管理器 🧩

虽然 TRSM 已足够,但了解底层原理有助于调试。下面是一个简化版的 Redis Session 存储工具类:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.*;
import java.util.Base64;

public class RedisSessionStore {

private static final String SESSION_PREFIX = "session:";
private static JedisPool jedisPool;

static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(20);
config.setMaxIdle(10);
jedisPool = new JedisPool(config, "192.168.1.20", 6379);
}

/**
* 保存 Session 对象到 Redis
*/

public static void saveSession(String sessionId, Object sessionData) {
try (Jedis jedis = jedisPool.getResource()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(sessionData);
oos.flush();
byte[] data = bos.toByteArray();
String encoded = Base64.getEncoder().encodeToString(data);
jedis.setex(SESSION_PREFIX + sessionId, 1800, encoded); // 30分钟过期
} catch (IOException e) {
throw new RuntimeException("Failed to serialize session", e);
}
}

/**
* 从 Redis 读取 Session
*/

public static Object getSession(String sessionId) {
try (Jedis jedis = jedisPool.getResource()) {
String encoded = jedis.get(SESSION_PREFIX + sessionId);
if (encoded == null) return null;
byte[] data = Base64.getDecoder().decode(encoded);
ByteArrayInputStream bis = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (Exception e) {
throw new RuntimeException("Failed to deserialize session", e);
}
}

/**
* 删除 Session
*/

public static void removeSession(String sessionId) {
try (Jedis jedis = jedisPool.getResource()) {
jedis.del(SESSION_PREFIX + sessionId);
}
}
}

⚠️ 注意:实际生产中应使用更安全的序列化方式(如 JSON、Protobuf),避免 Java 原生序列化的安全风险。


九、高级配置与优化 🚀

1. 会话粘性(Sticky Session) vs 无状态

  • Sticky Session:Nginx 将同一用户始终路由到同一 Tomcat。优点是减少跨节点 Session 访问;缺点是节点故障时需重新登录。
  • 无状态(Stateless):每次请求都从 Redis 读取 Session。更灵活,但增加 Redis 压力。

建议:开启 Sticky Session + Redis 会话共享,兼顾性能与容错。

2. 健康检查

在 Nginx 中配置主动健康检查(需商业版或使用第三方模块):

upstream tomcat_cluster {
zone tomcat_cluster 64k;

server 192.168.1.11:8080 max_fails=1 fail_timeout=10s;
server 192.168.1.12:8080 max_fails=1 fail_timeout=10s;
server 192.168.1.13:8080 max_fails=1 fail_timeout=10s;

# 被动健康检查已足够
}

或在 Tomcat 中暴露 /health 接口,由外部监控系统调用。

3. SSL/TLS 终止

在 Nginx 上配置 HTTPS,卸载 Tomcat 的加密负担:

server {
listen 443 ssl;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# … 其他配置
location / {
proxy_pass http://tomcat_cluster;
proxy_set_header X-Forwarded-Proto https;
}
}


十、常见问题排查 🛠️

1. Session 未共享

  • 检查 context.xml 中的 Manager 配置是否正确。
  • 确认 Redis 可访问(telnet 192.168.1.20 6379)。
  • 查看 Tomcat 日志是否有 ClassNotFoundException(缺少 JAR)。

2. 负载不均

  • 检查 Nginx 是否启用了 ip_hash(会导致同一 IP 始终访问同一节点)。
  • 使用 ab 或 wrk 压测,观察各节点日志。

3. Redis 连接泄漏

  • 确保使用连接池(如 JedisPool)。
  • 监控 Redis 的 connected_clients 数量。

十一、替代方案对比 📊

方案优点缺点适用场景
Redis 高性能、易部署 需维护 Redis 通用首选
Memcached 轻量、快速 不支持持久化 纯缓存场景
Tomcat 自带 DeltaManager 无需外部依赖 广播风暴、扩展性差 小型集群(≤3节点)
数据库(MySQL) 持久化、可靠 性能较低 对一致性要求极高

💡 对于大多数场景,Redis 是最佳选择。


十二、安全加固 🔒

  • Redis 密码认证:

    # redis.conf
    requirepass your_strong_password

    并在 context.xml 中添加 password="your_strong_password"。

  • 禁用 Redis 危险命令:

    rename-command FLUSHDB ""
    rename-command FLUSHALL ""

  • Nginx 隐藏版本号:

    server_tokens off;

  • Tomcat 安全:

    • 删除 webapps 下的默认应用(docs, examples 等)。
    • 限制管理端口访问。

  • 十三、总结 🎯

    通过本文,我们完成了:

    ✅ 部署多节点 Tomcat 集群 ✅ 配置 Nginx 实现负载均衡 ✅ 集成 Redis 实现会话共享 ✅ 编写 Java 代码验证集群行为 ✅ 提供生产环境优化建议

    Tomcat 集群部署虽有一定复杂度,但它是构建高可用 Java Web 应用的基石。掌握这一技能,将为你在企业级开发中打下坚实基础。

    🌟 最后建议:在生产环境中,务必结合监控(如 Prometheus + Grafana)、日志收集(ELK)和自动化部署(Ansible/Docker)来管理集群。


    附录:完整架构图 📐

    #mermaid-svg-woGmkCURshdehPca{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-woGmkCURshdehPca .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-woGmkCURshdehPca .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-woGmkCURshdehPca .error-icon{fill:#552222;}#mermaid-svg-woGmkCURshdehPca .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-woGmkCURshdehPca .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-woGmkCURshdehPca .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-woGmkCURshdehPca .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-woGmkCURshdehPca .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-woGmkCURshdehPca .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-woGmkCURshdehPca .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-woGmkCURshdehPca .marker{fill:#333333;stroke:#333333;}#mermaid-svg-woGmkCURshdehPca .marker.cross{stroke:#333333;}#mermaid-svg-woGmkCURshdehPca svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-woGmkCURshdehPca p{margin:0;}#mermaid-svg-woGmkCURshdehPca .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-woGmkCURshdehPca .cluster-label text{fill:#333;}#mermaid-svg-woGmkCURshdehPca .cluster-label span{color:#333;}#mermaid-svg-woGmkCURshdehPca .cluster-label span p{background-color:transparent;}#mermaid-svg-woGmkCURshdehPca .label text,#mermaid-svg-woGmkCURshdehPca span{fill:#333;color:#333;}#mermaid-svg-woGmkCURshdehPca .node rect,#mermaid-svg-woGmkCURshdehPca .node circle,#mermaid-svg-woGmkCURshdehPca .node ellipse,#mermaid-svg-woGmkCURshdehPca .node polygon,#mermaid-svg-woGmkCURshdehPca .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-woGmkCURshdehPca .rough-node .label text,#mermaid-svg-woGmkCURshdehPca .node .label text,#mermaid-svg-woGmkCURshdehPca .image-shape .label,#mermaid-svg-woGmkCURshdehPca .icon-shape .label{text-anchor:middle;}#mermaid-svg-woGmkCURshdehPca .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-woGmkCURshdehPca .rough-node .label,#mermaid-svg-woGmkCURshdehPca .node .label,#mermaid-svg-woGmkCURshdehPca .image-shape .label,#mermaid-svg-woGmkCURshdehPca .icon-shape .label{text-align:center;}#mermaid-svg-woGmkCURshdehPca .node.clickable{cursor:pointer;}#mermaid-svg-woGmkCURshdehPca .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-woGmkCURshdehPca .arrowheadPath{fill:#333333;}#mermaid-svg-woGmkCURshdehPca .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-woGmkCURshdehPca .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-woGmkCURshdehPca .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-woGmkCURshdehPca .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-woGmkCURshdehPca .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-woGmkCURshdehPca .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-woGmkCURshdehPca .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-woGmkCURshdehPca .cluster text{fill:#333;}#mermaid-svg-woGmkCURshdehPca .cluster span{color:#333;}#mermaid-svg-woGmkCURshdehPca div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-woGmkCURshdehPca .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-woGmkCURshdehPca rect.text{fill:none;stroke-width:0;}#mermaid-svg-woGmkCURshdehPca .icon-shape,#mermaid-svg-woGmkCURshdehPca .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-woGmkCURshdehPca .icon-shape p,#mermaid-svg-woGmkCURshdehPca .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-woGmkCURshdehPca .icon-shape rect,#mermaid-svg-woGmkCURshdehPca .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-woGmkCURshdehPca .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-woGmkCURshdehPca .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-woGmkCURshdehPca :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Session Store

    Application Servers

    Load Balancer

    HTTP/HTTPS

    Proxy

    Proxy

    Proxy

    Read/Write

    Read/Write

    Read/Write

    Client

    Nginx

    Tomcat Node 1\\njvmRoute=node1

    Tomcat Node 2\\njvmRoute=node2

    Tomcat Node 3\\njvmRoute=node3

    Redis Server\\n192.168.1.20:6379

    现在,你已经具备了构建高可用 Tomcat 集群的能力!动手实践吧,遇到问题欢迎留言讨论 💬。


    🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

    赞(0)
    未经允许不得转载:171主机测评 » Java 部署:Tomcat 集群部署(负载均衡 + 会话共享)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址