You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3部署外部Tomcat10会话集群异常:Spring服务会话不共享

Spring Boot 3.x + Tomcat 10 会话集群不共享问题排查与解决

核心原因分析

1. Tomcat Cluster配置错误(Manager位置放错)

你的Tomcat1的server.xml中,DeltaManager被错误嵌套在Channel标签内部,而正确位置应该是Cluster的直接子元素,与Channel同级。这个配置错误会导致Tomcat1无法正确初始化集群会话管理器,进而无法参与会话复制。

Tomcat1的错误配置片段:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <!-- 错误:Manager放在了Channel内部 -->
        <Manager className="org.apache.catalina.ha.session.DeltaManager"
           expireSessionsOnShutdown="false"
           notifyListenersOnReplication="true"/>
        ...
    </Channel>
    ...
</Cluster>

2. Spring Boot自动配置干扰Tomcat会话管理

Spring Boot默认会为嵌入式容器配置会话管理器,即使部署到外部Tomcat,部分自动配置仍可能生效,导致Tomcat的集群会话管理器无法接管会话处理。

3. 缺少Web层面的distributable声明

虽然你在Tomcat的Context中设置了distributable="true",但如果WAR包的web.xml中没有<distributable/>标签,Servlet规范要求的分布式会话标识不完整,会导致Spring Boot的会话处理不触发集群复制。


解决方案

1. 修正Tomcat Cluster的Manager配置位置

将Tomcat1的DeltaManager移到Cluster标签下,与Channel同级,和Tomcat2的配置保持一致:

修正后的Tomcat1 Cluster配置片段:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
    <!-- 正确:Manager作为Cluster的直接子元素 -->
    <Manager className="org.apache.catalina.ha.session.DeltaManager"
       expireSessionsOnShutdown="false"
       notifyListenersOnReplication="true"/>
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <!-- 移除Channel内部的Manager -->
        <Receiver 
            address="127.0.0.1" 
            port="3200" 
            autoBind="100" 
            selectorTimeout="5000"
            maxThreads="6" 
            className="org.apache.catalina.tribes.transport.nio.NioReceiver"/>
        <!-- 其他Channel配置保持不变 -->
    </Channel>
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

2. 禁用Spring Boot的自动会话管理器配置

在Spring Boot启动类上排除会话自动配置,让外部Tomcat的集群管理器生效:

import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(exclude = {SessionAutoConfiguration.class})
public class YourApplication extends SpringBootServletInitializer {
    // 原有代码保持不变
}

3. 添加Web层面的distributable声明

在项目src/main/webapp/WEB-INF目录下创建web.xml文件,添加分布式会话标识:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <distributable/>
</web-app>

4. 验证会话ID格式

测试时检查返回的sessionId是否包含jvmRoute后缀(如xxxx.tomcat1、xxxx.tomcat2),这表明Tomcat的集群会话管理器已正确识别会话归属。如果会话ID前后不一致,需检查Tomcat的集群端口(3200、3201)是否被防火墙或其他进程占用。

内容的提问来源于stack exchange,提问作者watercolor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 10:19:52