使用 Traefik 进行 Spring 启动 Tomcat 会话复制

问题描述 投票:0回答:1

我正在尝试使用 Spring boot 和 Traefik 设置会话复制。我在以下链接中找到了如何使用 Tomcat 及其

server.xml
文件来实现它:Docker swarm 中的 Tomcat 会话复制

我的整个应用程序看起来就像这个存储库中的应用程序https://github.com/trajano/tomcat-docker-swarm(撰写文件、JSP 页面等)。

不同的是我使用以下 dockerfile:

FROM tomcat:10-jdk17-openjdk-slim

WORKDIR /app

COPY build/libs/demo-0.0.1-SNAPSHOT.war app.war

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/app/app.war"]

但是,我无法使用带有嵌入式 Tomcat 的 Spring Boot 使其工作。我还发现这篇文章展示了如何使用嵌入式 tomcat 设置它:如何使用 Spring Boot 嵌入式 tomcat 设置 Tomcat 会话复制,但它使用

StaticMembershipInterceptor
并且我无法使用
CloudMembershipService
让它工作.

我当前的配置类如下所示:

@Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCust() {
        return factory -> {
            factory.addContextCustomizers(tomcatContextCutomizer());
        };
    }
    private TomcatContextCustomizer tomcatContextCutomizer() {
        return context -> {

            DeltaManager deltaManager = new DeltaManager();
            deltaManager.setNotifyListenersOnReplication(true);
            deltaManager.setExpireSessionsOnShutdown(false);

            context.setManager(deltaManager);

            SimpleTcpCluster simpleTcpCluster = new SimpleTcpCluster();

            simpleTcpCluster.registerManager(deltaManager);

            GroupChannel channel = new GroupChannel();

            NioReceiver receiver = new NioReceiver();
            channel.setChannelReceiver(receiver);

            ReplicationTransmitter sender = new ReplicationTransmitter();
            sender.setTransport(new PooledParallelSender());

            channel.setChannelSender(sender);

            channel.addInterceptor(new TcpPingInterceptor());
            channel.addInterceptor(new TcpFailureDetector());
            channel.addInterceptor(new MessageDispatchInterceptor());


            simpleTcpCluster.addValve(new ReplicationValve());
            simpleTcpCluster.addValve(new JvmRouteBinderValve());
            simpleTcpCluster.addClusterListener(new ClusterSessionListener());

            CloudMembershipService clms = new CloudMembershipService();

            channel.setUtilityExecutor(new ScheduledThreadPoolExecutor(10));

            clms.setChannel(channel);
            channel.setMembershipService(clms);

            MembershipProvider mp = new DNSMembershipProvider();
            clms.setMembershipProvider(mp);

            mp.setMembershipService(channel.getMembershipService());

            simpleTcpCluster.setChannel(channel);

            Host host = (Host)context.getParent();
            host.setCluster(simpleTcpCluster);
        };
    }

此代码的结果是,我能够看到容器由于日志消息而彼此看到:

CloudMembershipProvider  : Member added: org.apache.catalina.tribes.membership.MemberImpl[tcp://1.2.3.4:0,1.2.3.4,0, alive=-1, securePort=-1, UDP Port=-1, id={1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 }, payload={}, command={}, domain={}]`.<br><br>
But the session never get's replicated. Some logs implying what may be happening are: <br>
`DeltaManager     : Manager []: skipping state transfer. No members active in cluster group. <br>


ReplicationValve     : Cluster is standalone: reset Session Request Delta at context []

使用

context.setDistributable(true)
没有帮助。

我正在使用 Spring boot 2.7.18 和相应的 Tomcat 版本 9.0.83。

spring-boot cluster-computing war traefik tomcat9
1个回答
0
投票

我发现了问题。我将为任何想要为会话复制提供开箱即用配置的人保留这个问题。

您不应该创建新的 MembershipProvider,而是需要指定提供者的名称。

调整后的配置为:

  DeltaManager deltaManager = new DeltaManager();
  deltaManager.setNotifyListenersOnReplication(true);
  deltaManager.setExpireSessionsOnShutdown(false);
  context.setManager(deltaManager);

  SimpleTcpCluster simpleTcpCluster = new SimpleTcpCluster();

  simpleTcpCluster.registerManager(deltaManager);

  GroupChannel channel = new GroupChannel();

  NioReceiver receiver = new NioReceiver();
  channel.setChannelReceiver(receiver);

  ReplicationTransmitter sender = new ReplicationTransmitter();
  sender.setTransport(new PooledParallelSender());

  channel.setChannelSender(sender);

  channel.addInterceptor(new TcpPingInterceptor());
  channel.addInterceptor(new TcpFailureDetector());
  channel.addInterceptor(new MessageDispatchInterceptor());


  simpleTcpCluster.addValve(new ReplicationValve());
  simpleTcpCluster.addValve(new JvmRouteBinderValve());
  simpleTcpCluster.addClusterListener(new ClusterSessionListener());

  CloudMembershipService clms = new CloudMembershipService();

  channel.setUtilityExecutor(new ScheduledThreadPoolExecutor(10));

  clms.setChannel(channel);
  channel.setMembershipService(clms);

  clms.setMembershipProviderClassName(DNSMembershipProvider.class.getName());


  simpleTcpCluster.setChannel(channel);

  Engine engine = (Engine)context.getParent().getParent();
  engine.setCluster(simpleTcpCluster);
};

  clms.setMembershipProviderClassName(DNSMembershipProvider.class.getName());


  simpleTcpCluster.setChannel(channel);

  Engine engine = (Engine)context.getParent().getParent();
  engine.setCluster(simpleTcpCluster);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.