skip to Main Content

I’m seeing many posts achieving Tomcat session replication in docker swarm using traefik. But I just don’t want to add another component. I use httpd as frontend for tomcat. Tomcat will be deployed as a service with 4 replicas and will be scaled when required. httpd is running as docker service and both are in same network. My question is, is there any way to achieve Tomcat session replication in docker swarm in this case. TIA.

2

Answers


  1. As long as all Tomcat Docker containers are reachable you can achieve this by below Cluster setup.

    The below setup is for tomcat 7 but should work in the same way for other versions also.

    In case of Apache Tomcat 7 uncomment <Cluster className=”org.apache.catalina.ha.tcp.SimpleTcpCluster”/> tag and update cluster detail something like below.

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
        <Manager className="org.apache.catalina.ha.session.DeltaManager"
            expireSessionsOnShutdown="false"        
            notifyListenersOnReplication="true"/>
        
        <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        
            <Membership className="org.apache.catalina.tribes.membership.McastService"
            address="228.0.0.4"
            port="45564" frequency="500"
            dropTime="3000"/>           
    
            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">                
                <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>              
            </Sender>           
            
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
            address="auto" port="4000" autoBind="100"
            selectorTimeout="5000" maxThreads="6"/>                     
            
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>         
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>   
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>                      
        
        </Channel>
        
        <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" />       
        <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />       
        
    </Cluster>
    

    Also, we need to add workers.properties at apache/conf/ path.

    Please note this file has to be placed in all the Tomcat servers which will run in a cluster.

    You can read more in detail here.

    Login or Signup to reply.
  2. You can do this without a front end, BUT you’re going to have issues because if the ingress routes to a different node, that node has to request the session from another node.

    The plain tomcat image is not sufficient to do clustering, it wouild need some customizations to /usr/local/tomcat/conf/server.xml to the cluster configuration to use the DNSMembershipProvider

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
      <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership
          className="org.apache.catalina.tribes.membership.cloud.CloudMembershipService"
          membershipProviderClassName="org.apache.catalina.tribes.membership.cloud.DNSMembershipProvider"
        />
      </Channel>
    </Cluster>
    

    DNSMembershipProvider uses the environment variable DNS_MEMBERSHIP_SERVICE_NAME to look up the server so it should match the service name.

    The following docker-compose.yml shows how to deploy it without any other component.

    version: "3.8"
    services:
      tomcat:
        build: ./tomcat
        image: sample-tomcat
        environment:
          - DNS_MEMBERSHIP_SERVICE_NAME=tomcat
        ports:
          - 50000:80
        deploy:
          replicas: 6
          update_config:
            order: start-first
    

    Proper way

    As I stated earlier, using the above approach will satisfy the OP’s requirements of not adding an additional component, but will have significant performance issues. Instead you need a proxy that can route to the servers with the following features:

    1. session stickiness
    2. Docker Swarm service label discovery
    3. health check to reduce potential user impact by detecting a server is down beforehand.

    Traefik handles all the requirements quite nicely even if itself does not support clustering due to their ACME storage not allowing concurrent access without going to their EE version.

    The docker-compose.yml would be as follows.

    version: "3.8"
    services:
      proxy:
        image: traefik:2.6
        command:
          - "--providers.docker.swarmMode=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.app.address=:80"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
        ports:
          - 50000:80
      tomcat:
        build: ./tomcat
        image: sample-tomcat
        environment:
          - DNS_MEMBERSHIP_SERVICE_NAME=tomcat
        deploy:
          replicas: 6
          labels:
            - "traefik.enable=true"
            - "traefik.http.routers.app.entrypoints=app"
            - "traefik.http.routers.app.rule=Host(`localhost`)"
            - "traefik.http.services.app-service.loadBalancer.sticky.cookie=true"
            - "traefik.http.services.app-service.loadBalancer.sticky.cookie.httponly=true"
            - "traefik.http.services.app-service.loadbalancer.server.port=8080"
            - "traefik.http.services.app-service.loadbalancer.healthcheck.path=/"
          update_config:
            order: start-first
          endpoint_mode: dnsrr
    

    One property of note is endpoint_mode: dnsrr is not available when exposing ports earlier. This enables a better replication of session data within the Tomcat cluster as each node will have individual IDs.

    An example implementation of this is in my github repo https://github.com/trajano/tomcat-docker-swarm

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search