linux服务-Nginx+Tomcat+Redis之Session 共享

Nginx+Tomcat+Redis之Session 共享

一、原理

参考:tomcat原理redis 集群原理与部署nginx原理与安装nginx配置章节示例配置归集

1.1、服务说明

  • Nginx:作为前端反向代理和负载均衡器,接收所有客户端请求,按配置规则分发到后端多个 Tomcat 节点,实现请求分流(负载均衡)。

  • Tomcat 集群:多个 Tomcat 实例部署相同的业务应用,并行处理 Nginx 转发的请求,提升系统并发能力和可用性(单节点故障不影响整体服务)。

  • Redis:作为分布式 Session 存储中心,所有 Tomcat 节点将 Session 数据统一写入 Redis,读取 Session 时也从 Redis 获取,实现多节点 Session 共享。

  • keepalived: 如果没有F5之类的负载可以在加个kp服务(本章没加,还没复习到)

  • 逻辑图

  • 会话逻辑图

1.2、负载&会话共享原理

  • 负载均衡原理(Nginx 侧)
    • Nginx 通过upstream模块定义 Tomcat 集群,支持多种负载均衡策略:
      • 轮询(默认):请求挨个分,Tomcat 性能一致用。
      • 权重(weight):性能好的多接单。
      • IP 哈希(ip_hash):基于客户端 IP 哈希分配节点,同一用户固定连一个 Tomcat(会影响负载均衡均匀性)。
      • URL 哈希(url_hash):同一网址固定连一个 Tomcat(适合静态资源)。
  • Session 共享原理(Redis+Tomcat 侧)
    • 默认情况下,Tomcat 的 Session 存储在本地 JVM 内存中,多节点部署时会出现 "Session 不一致" 问题(如用户在 Tomcat1 登录后,请求被转发到 Tomcat2,因 Tomcat2 无该 Session 导致重新登录)。
    • 解决方案 :将 Session 从 "Tomcat 本地内存" 迁移到 "分布式 Redis",流程如下:
      1. 用户首次登录:Tomcat1 验证账号密码成功后,生成 Session 对象,通过Tomcat-Redis-Session-Manager插件将 Session 数据(SessionID、用户信息、过期时间等)写入 Redis。
      2. 后续请求:Nginx 将请求转发到任意 Tomcat 节点(如 Tomcat2),Tomcat2 通过 SessionID 从 Redis 读取 Session 数据,验证用户状态,实现 "一次登录,多节点共享"。
      3. Session 过期:Redis 自动维护 Session 的过期时间(与 Tomcat Session 过期时间一致),过期后自动删除,避免垃圾数据堆积。

二、安装配置

2.1、环境准备

  • 组件说明

    组件 版本建议 作用
    Nginx 1.29 反向代理 + 负载均衡
    Tomcat 8.5.100 应用服务器( 2 个节点)
    Redis 7.2.12 分布式 Session 存储
    JDK 1.8.461 Tomcat 运行依赖
    操作系统 CentOS 7 / 麒麟10 服务器环境
  • 节点规划&端口划分

    节点 ip地址 tomcat redis集群 nginx
    node1 10.4.50.130 18080 6379,6380 8080
    node2 10.4.50.139 18080 6379,6380 -
    node3 10.4.50.167 18080 6379,6380 -
  • 安装配置

  • 关闭防火墙或开放端口:

    bash 复制代码
    # 临时关闭防火墙(CentOS)
    systemctl stop firewalld
    # 仅8080对外访问的节点开全局防火培
    firewall-cmd --permanent --add-port=8080/tcp
    
    # 其它端口间访问用富策略,三台之间互通就行,
    # 避免生产用久了要修复版本漏洞怪麻烦,如果在机房 ssh端口都建议关掉
    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.4.50.130" protocol value="tcp" accept'
    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.4.50.139" protocol value="tcp" accept'
    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.4.50.167" protocol value="tcp" accept'
    firewall-cmd --reload
    
    # 部署前先 stop, 实际用的时候在打开防火墙
    # 如果要单个放  列表: 18080,6379,6380,16379,16380,8080

2.2、开始配置

  • 部署redis session插件

    bash 复制代码
    # 下载 SLF4J API 包(核心依赖)
    wget https://repo.huaweicloud.com/repository/maven/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar
    
    # 下载 SLF4J 简单绑定包(避免 "Failed to load class org.slf4j.impl.StaticLoggerBinder" 警告)
    wget https://repo.huaweicloud.com/repository/maven/org/slf4j/slf4j-simple/1.7.36/slf4j-simple-1.7.36.jar
    
    # 下载 Jedis(Redis 客户端)
    wget https://repo.huaweicloud.com/repository/maven/redis/clients/jedis/3.6.3/jedis-3.6.3.jar
    
    # 下载 commons-pool2(Jedis 连接池依赖)
    wget https://repo.huaweicloud.com/repository/maven/org/apache/commons/commons-pool2/2.11.1/commons-pool2-2.11.1.jar
    
    redis-session-cluster-plugin.jar  <-- 用豆包ai生成的,有点长,已放网盘 or 对应的jar包 顶上的示例配置归集也有
  • 配置 Tomcat 的 conf/context.xml

    • 单机redis

      bash 复制代码
      <Context>
          <!-- Redis Session共享配置 -->
          <Valve className="com.naritech.nicole.gump.RedisSessionHandlerValve" />
          <Manager className="com.naritech.nicole.gump.RedisSessionManager"
                   host="192.168.1.100"  <!-- Redis服务器IP -->
                   port="6379"           <!-- Redis端口 -->
                   password="123456"     <!-- Redis密码(无则省略) -->
                   database="0"          <!-- Redis数据库编号(默认0) -->
                   maxInactiveInterval="1800"  <!-- Session过期时间(秒,与Tomcat默认一致) -->
                   timeout="2000"        <!-- Redis连接超时时间 -->
                   />
      </Context>
    • 集群redis <--- 当前示例 完整的整个配置

      bash 复制代码
      <?xml version="1.0" encoding="UTF-8"?>
      <Context>
          <WatchedResource>WEB-INF/web.xml</WatchedResource>
          <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
          <Resources cachingAllowed="true" cacheMaxSize="102400" />
      
          <!-- Redis Cluster Session 共享配置(正确闭合格式) -->
          <Valve className="com.naritech.nicole.gump.RedisSessionHandlerValve" />
          <Manager className="com.naritech.nicole.gump.RedisSessionManager"
                   nodes="10.4.50.130:6379,10.4.50.139:6379,10.4.50.167:6379,10.4.50.130:6380,10.4.50.139:6380,10.4.50.167:6380"
                   password="xiong"
                   database="0"
                   maxInactiveInterval="1800"
                   timeout="3000"
                   maxRedirections="5"
                   cluster="true" />
      </Context>
    • 主从+哨兵模式

      bash 复制代码
      # 只需填哨兵节点地址
      <Manager className="com.naritech.nicole.gump.RedisSessionHandlerValve"
               sentinelMaster="mymaster"  <!-- 哨兵监控的主节点名称 -->
               sentinels="192.168.1.100:26379,192.168.1.103:26379"  <!-- 哨兵节点列表 -->
               password="123456"
               database="0"
               maxInactiveInterval="1800"
               />
  • 部署测试应用(验证 Session 共享)

    bash 复制代码
    mkdir /data/tomcat18080/webapps/ROOT/
    vim /data/tomcat18080/webapps/ROOT/index.jsp
    
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ page import="java.net.InetAddress" %>
    <%@ page import="java.net.NetworkInterface" %>
    <%@ page import="java.util.Enumeration" %>
    <%@ page import="java.io.File" %>
    
    <html>
    <head>
        <title>Tomcat 核心信息查询(含运行路径)</title>
    </head>
    <body>
        <h3>🎯 Tomcat 核心信息汇总</h3>
        <hr>
        <p><strong>📌 Session 信息:</strong></p>
        <p>Session ID:<%= session.getId() %></p>
        <p>创建时间:<%= new java.util.Date(session.getCreationTime()) %></p>
        <p>最后活动时间:<%= new java.util.Date(session.getLastAccessedTime()) %></p>
        <p>会话超时时间:<%= session.getMaxInactiveInterval() / 60 %> 分钟</p>
        <hr>
        <p><strong>🖥️ 服务器信息:改成服务器ip </strong></p>
    </body>
    </html>
    • 三台都要加上,然后访问 ip:18080
  • nginx配置,放到 conf.d/tomcat.conf下

    bash 复制代码
    upstream backend_servers {
        server 10.4.50.130:18080 weight=5;  # 服务器 1,权重 5(请求占比更高)
        server 10.4.50.139:18080 weight=3;  # 服务器 2,权重 3
        server 10.4.50.167:18080 weight=3;  # 服务器 2,权重 3
    }
    
    # 反向代理的 server 块
    server {
        listen       8080;
        server_name  127.0.0.1;  # 客户端访问的域名
    
        # 所有请求转发到 backend_servers 集群
        location / {
            proxy_pass http://backend_servers;  # 转发到负载均衡集群
            proxy_set_header Host $host;  # 传递客户端 Host 头到后端
            proxy_set_header X-Real-IP $remote_addr;  # 传递客户端真实 IP 到后端
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 传递代理
            proxy_connect_timeout 30;  # 与后端服务器连接超时时间
            proxy_read_timeout 60;  # 读取后端响应超时时间
        }
    }

2.3、功能验证

  • 如果nginx访问一台正常, 其它500,那就只能说明你的session会话没有配对,在多检查一下

  • 正常如下

三、补充

3.1关键注意事项

  1. Redis 高可用:生产环境需部署 Redis 主从 + 哨兵或 Redis Cluster,避免 Redis 单点故障导致 Session 丢失。
  2. Session 过期时间 :Tomcat 的maxInactiveInterval需与 Redis 的 Session 过期时间一致(默认 1800 秒,即 30 分钟)。
  3. Jar 包版本兼容:Tomcat、Jedis、commons-pool2 的版本需匹配(如 Tomcat8.5 推荐 Jedis 3.x,避免版本冲突导致 Session 写入失败)。
  4. Nginx 转发配置 :必须添加proxy_set_header传递客户端信息,否则 Tomcat 会将 Nginx 的 IP 当作客户端 IP,可能导致 IP 哈希策略失效。
相关推荐
dyxal2 小时前
linux系统上 WPS Office新增字体
linux·运维·wps
码河漫步2 小时前
vmware安装ubuntu22.04
linux·运维
u***1373 小时前
详解tomcat中的jmx监控
java·tomcat
IDOlaoluo3 小时前
apache-tomcat-7.0.42.tar.gz 下载与安装完整教程(附安装包)
java·tomcat·apache
杜子不疼.3 小时前
【Linux】进程状态全解析:从 R/S/D/T 到僵尸 / 孤儿进程
linux·人工智能·ai
序属秋秋秋4 小时前
《Linux系统编程之进程基础》【进程优先级】
linux·运维·c语言·c++·笔记·进程·优先级
加勒比之杰克4 小时前
【操作系统原理】Linux 进程控制
linux·运维·服务器·进程控制
XH-hui6 小时前
【打靶日记】TheHackerLabs 之 THLPWN
linux·网络安全·thehackerlabs·thl
刘一说8 小时前
一次生产环境 Tomcat 7 + JDK 7 应用启动失败的完整排查与修复实录
java·tomcat·firefox