如何在Spring Boot嵌入式Tomcat中配置Tomcat会话复制
Spring Boot嵌入式Tomcat会话复制实现指南
一、依赖配置
Spring Boot的spring-boot-starter-web默认不包含Tomcat集群相关组件,需手动引入HA依赖,注意版本要与Spring Boot内置Tomcat版本匹配(比如Spring Boot 2.7.x对应Tomcat 9.0.x,3.x对应Tomcat 10.x):
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina-ha</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-tribes</artifactId> <version>${tomcat.version}</version> </dependency>
二、Java代码配置
通过自定义TomcatServletWebServerFactory配置Tomcat集群与会话复制逻辑:
import org.apache.catalina.ha.tcp.SimpleTcpCluster; import org.apache.catalina.ha.tcp.ReplicationValve; import org.apache.catalina.ha.session.DeltaManager; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatClusterConfig { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatClusterCustomizer() { return factory -> { factory.addContextCustomizers(context -> { // 初始化Tomcat集群实例 SimpleTcpCluster cluster = new SimpleTcpCluster(); // 使用DeltaManager实现会话增量复制(比全量复制效率更高) DeltaManager deltaManager = new DeltaManager(); cluster.setManager(deltaManager); // 添加复制阀门,过滤需要触发会话复制的请求路径 ReplicationValve replicationValve = new ReplicationValve(); replicationValve.setFilter(".*\\.jsp$|.*\\.api$"); cluster.addValve(replicationValve); // 配置集群基础属性 cluster.setClusterName("spring-boot-tomcat-cluster"); cluster.setChannelSendOptions(8); // 异步发送复制消息 // 为当前上下文绑定集群 context.setCluster(cluster); }); }; } }
三、启动参数配置
添加JVM启动参数确保集群通信正常:
-Dcatalina.base=./tomcat-instance -Djava.net.preferIPv4Stack=true
catalina.base:指定嵌入式Tomcat的基础目录,用于存储集群临时文件preferIPv4Stack=true:避免IPv6环境下的组播通信异常
四、测试验证
- 打包应用为可执行JAR
- 启动两个不同端口的实例:
java -jar your-app.jar --server.port=8080 java -jar your-app.jar --server.port=8081 - 在8080端口创建会话(比如登录操作),切换到8081端口验证会话是否同步
为何嵌入式Tomcat会话复制的指南如此匮乏?
- Spring官方主推Spring Session:Spring Boot官方更推荐Spring Session结合Redis/MongoDB等实现会话共享,这类方案跨容器、适配云原生环境,配置更简单,导致Tomcat原生方案被边缘化。
- Tomcat原生集群实用性低:Tomcat会话复制依赖组播或静态成员配置,云环境(如K8s)中组播通常不可用,静态成员配置繁琐,场景局限性大。
- 嵌入式Tomcat API门槛高:Spring Boot未对Tomcat集群功能做自动化封装,需手动操作底层API,实现成本高,社区实践自然较少。
- 跨容器场景限制:Tomcat原生会话复制仅适用于Tomcat集群,无法跨Jetty、Undertow等其他Servlet容器使用,不适用于微服务多容器混合部署场景。
内容的提问来源于stack exchange,提问作者Lifeweaver
相关产品推荐
相关产品推荐

