> Can you show us how you configured this cluster please?

Sure.

Tomcat tomcat = new Tomcat();
tomcat.setBaseDir(baseDir);
tomcat.getServer().setAddress("127.0.0.1");
tomcat.getServer().setPort(shutDownPort);

tomcat.getServer().setShutdown("SHUTDOWN");
tomcat.getServer().addLifecycleListener(new AprLifecycleListener());
tomcat.getServer().addLifecycleListener(new JreMemoryLeakPreventionListener());
tomcat.getServer().addLifecycleListener(new GlobalResourcesLifecycleListener());
tomcat.getServer().addLifecycleListener(new
ThreadLocalLeakPreventionListener());

tomcat.setPort(httpPort);
tomcat.getConnector().getPort();//The default connector will only be
created if getConnector is called

LaunchServerHelper.addRemoteIpValve(tomcat);

//...

StandardHost hostManage = getStandardHost(tomcat, "manage." +
sgDomain, "sg-manage", serverProperties);
tomcat.getEngine().addChild(hostManage);

tomcat.start();
tomcat.getServer().await();
tomcat.stop();


private static StandardHost getStandardHost(Tomcat tomcat, String
name, String module, Properties serverProperties) {
  StandardHost host = new StandardHost();

  modifyHost(tomcat, name, module, host, serverProperties);
  return host;
}


private static void modifyHost(Tomcat tomcat, String name, String
module, StandardHost host, Properties serverProperties) {
  String webappDirLocation = module + "/src/main/webapp/";
  File webAppDir = new File(webappDirLocation);

  host.setName(name);
  String[] aliases = serverProperties.getProperty("tomcat-" + module +
"-aliases", "").split(",");
  for (String alias : aliases) {
    if (alias.length() > 0) {
      logger.log(Level.INFO, "Adding alias {0} for {1}", new Object[]
{alias, module});
      host.addAlias(alias);
    }
  }
  host.setParent(tomcat.getEngine());
  host.setAppBase(webAppDir.getAbsolutePath());

  StandardContext ctx = (StandardContext) tomcat.addWebapp(host, "/",
webAppDir.getAbsolutePath());
  ((StandardJarScanner) ctx.getJarScanner()).setScanManifest(false);
  ctx.setCookieProcessor(new LegacyCookieProcessor());

  // Declare an alternative location for your "WEB-INF/classes" dir
  // Servlet 3.0 annotation will work
  File additionWebInfClasses = new File(module + "/target/classes");
  WebResourceRoot resources = new StandardRoot(ctx);
  resources.addPreResources(new DirResourceSet(resources,
"/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
  ctx.setResources(resources);

  LaunchServerHelper.addSimpleTcpCluster(host, 4000, serverProperties);
}


public static void addSimpleTcpCluster(StandardHost host, int port,
Properties serverProperties) {
  if (!serverProperties.containsKey("tomcat-clusterMemberCount")) {
    return;
  }

  SimpleTcpCluster cluster = new SimpleTcpCluster();
  cluster.setClusterName("SG-cluster");
  cluster.setChannelStartOptions(3);
  cluster.setChannelSendOptions(8);

  {
    DeltaManager clusterManager = new DeltaManager();
    clusterManager.setName("SG-cluster-manager");
    clusterManager.setExpireSessionsOnShutdown(false);
    clusterManager.setNotifyListenersOnReplication(true);
    cluster.registerManager(clusterManager);
  }

  {
    GroupChannel channel = new GroupChannel();
    channel.setName("SG-channel");
    {
      NioReceiver channelReceiver = new NioReceiver();
      
channelReceiver.setAddress(serverProperties.getProperty("tomcat-clusterAddress"));
      channelReceiver.setPort(port);
      channelReceiver.setAutoBind(100);
      channelReceiver.setSelectorTimeout(5000);
      channelReceiver.setMaxThreads(6);
      channel.setChannelReceiver(channelReceiver);
    }
    cluster.setChannel(channel);

    {
      StaticMembershipInterceptor interceptor = new
StaticMembershipInterceptor();
      int clusterMemberCount =
Integer.parseInt(serverProperties.getProperty("tomcat-clusterMemberCount"));
      {
        StaticMember localMember = new StaticMember();
        localMember.setPort(port);
        localMember.setSecurePort(-1);
        
localMember.setHost(serverProperties.getProperty("tomcat-clusterAddress"));
        localMember.setDomain("publish-cluster");
        
localMember.setUniqueId(serverProperties.getProperty("tomcat-clusterMemberUniqueId"));
        interceptor.setLocalMember(localMember);
        interceptor.addStaticMember(localMember);
      }
      for (int i = 1; i <= clusterMemberCount; i++) {
        StaticMember member = new StaticMember();
        member.setLocal(false);
        member.setPort(port);
        member.setSecurePort(-1);
        
member.setHost(serverProperties.getProperty("tomcat-clusterMemberAddress"
+ i));
        member.setDomain("publish-cluster");
        
member.setUniqueId(serverProperties.getProperty("tomcat-clusterMemberUniqueId"
+ i));
        interceptor.addStaticMember(member);
      }
      channel.addInterceptor(interceptor);
    }
    channel.addInterceptor(new TcpPingInterceptor());
    channel.addInterceptor(new TcpFailureDetector());
    channel.addInterceptor(new MessageDispatchInterceptor());
  }


  ReplicationTransmitter replicationTransmitter = new ReplicationTransmitter();
  PooledParallelSender sender = new PooledParallelSender();
  sender.setTimeout(60000);
  sender.setMaxRetryAttempts(5);
  replicationTransmitter.setTransport(sender);

  ReplicationValve replicationValve = new ReplicationValve();
  replicationValve.setFilter("");
  cluster.addValve(replicationValve);
  cluster.addValve(new JvmRouteBinderValve());

  FarmWarDeployer farmDeployer = new FarmWarDeployer();
  farmDeployer.setTempDir("/tmp/war-temp/");
  farmDeployer.setDeployDir("/tmp/war-deploy/");
  farmDeployer.setWatchDir("/tmp/war-listen/");
  farmDeployer.setWatchEnabled(false);
  cluster.setClusterDeployer(farmDeployer);

  //cluster.addClusterListener(new
JvmRouteSessionIDBinderListener());//Removed in Tomcat 8.
https://tomcat.apache.org/migration-8.html#Clustering
  cluster.addClusterListener(new ClusterSessionListener());

  host.setCluster(cluster);
}


tomcat-clusterAddress=192.168.0.2
tomcat-clusterMemberUniqueId={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}
tomcat-clusterMemberCount=1
tomcat-clusterMemberAddress1=192.168.0.3
tomcat-clusterMemberUniqueId1={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}


This was initially converted from a server.xml configuration a year ago on
Tomcat 7 with minor modifications as we've upgraded to Tomcat 8 then 9.

Cheers,

Tim


On Thu, Oct 8, 2020 at 10:17 PM Mark Thomas <ma...@apache.org> wrote:

> On 08/10/2020 10:04, Tim N wrote:
> > Hi,
> >
> > I'm in the early stages of analysing this problem:
> >
> >    - Tomcat Embedded 9.0.37 with clustering enabled
> >    - SpringBoot application, 2.1.16
> >    - Login with no existing JSESSIONID fails
> >
> > I can see the following code is executed twice within one request, the
> > login attempt:
> >
> >
> *~/.m2/repository/org/apache/tomcat/tomcat-catalina/9.0.37/tomcat-catalina-9.0.37-sources.jar!/org/apache/catalina/session/ManagerBase.java:677*
> >
> >     public void add(Session session) {
> >         sessions.put(session.getIdInternal(), session);
> >
> > The first time it's executed, the session with the Spring context is
> added.
> > The second time it's executed, a second session with the same ID, but
> > without the Spring context, or any other session attribute I add for that
> > matter, overwrites the existing session, and login fails. If I debug and
> > prevent this by renaming the second session ID, login works because the
> > original session is preserved.
> >
> > The stack-trace for the first call is shown below:
> >
> > add:678, ManagerBase (org.apache.catalina.session)
> > setId:358, StandardSession (org.apache.catalina.session)
> > setId:327, DeltaSession (org.apache.catalina.ha.session)
> > setId:345, DeltaSession (org.apache.catalina.ha.session)
> > createSession:719, ManagerBase (org.apache.catalina.session)
> > createSession:422, DeltaManager (org.apache.catalina.ha.session)
> > createSession:410, DeltaManager (org.apache.catalina.ha.session)
> > doGetSession:3043, Request (org.apache.catalina.connector)
> > getSession:2441, Request (org.apache.catalina.connector)
>
> <snip/>
>
> This is the app triggering the creation of the session.
>
> > The stack-trace for the second call is shown below:
> >
> > add:678, ManagerBase (org.apache.catalina.session)
> > setId:358, StandardSession (org.apache.catalina.session)
> > setId:327, DeltaSession (org.apache.catalina.ha.session)
> > handleSESSION_CREATED:1322, DeltaManager (org.apache.catalina.ha.session)
> > messageReceived:1192, DeltaManager (org.apache.catalina.ha.session)
>
> <snip/>
>
> This is the DeltaManager receiving notification that a new session has
> been created.
>
> > Any help would be appreciated. I can replicate this every time and spend
> > some time investigating this.
>
> The new session created message should be send to (and then processed
> on) every node *except* the node on which the session was originally
> created.
>
> Can you show us how you configured this cluster please?
>
> Mark
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>

Reply via email to