docker swarm 中的 Tomcat 会话复制



我看到很多帖子使用 traefik 在 docker 群中实现了 Tomcat 会话复制。但我只是不想添加另一个组件。我使用 httpd 作为 tomcat 的前端。Tomcat 将部署为具有 4 个副本的服务,并将在需要时进行扩展。httpd 作为 docker 服务运行,两者位于同一网络中。我的问题是,在这种情况下,有没有办法在 docker 群中实现 Tomcat 会话复制。蒂亚。

只要所有 Tomcat Docker 容器都可以访问,就可以通过下面的集群设置来实现这一点。

以下设置适用于 tomcat 7,但对于其他版本也应该以相同的方式工作。

如果是Apache Tomcat 7,请取消注释<Cluster className=”org.apache.catalina.ha.tcp.SimpleTcpCluster”/>标记并更新集群详细信息,如下所示。

<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>

此外,我们需要apache/conf/路径添加workers.properties

请注意,此文件必须放置在将在集群中运行的所有Tomcat服务器中。

您可以在此处阅读更多详细信息。

您可以在没有前端的情况下执行此操作,但是您会遇到问题,因为如果入口路由到其他节点,则该节点必须从另一个节点请求会话。

普通的雄猫映像不足以进行群集,它需要一些自定义来/usr/local/tomcat/conf/server.xml群集配置以使用该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使用环境变量DNS_MEMBERSHIP_SERVICE_NAME来查找服务器,使其应与服务名称匹配。

以下docker-compose.yml演示如何在没有任何其他组件的情况下部署它。

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

正确的方式

如前所述,使用上述方法将满足OP不添加额外组件的要求,但会产生严重的性能问题。 相反,您需要一个可以路由到具有以下功能的服务器的代理:

  1. 会话粘性
  2. 码头工人群服务标签发现
  3. 运行状况检查通过事先检测服务器关闭来减少潜在的用户影响。

Traefik 可以很好地处理所有要求,即使它不支持集群,因为他们的 ACME 存储不允许并发访问而不转到他们的 EE 版本。

docker-compose.yml如下。

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

一个需要注意的属性是endpoint_mode: dnsrr之前公开端口时不可用。 这样可以更好地复制 Tomcat 集群中的会话数据,因为每个节点都有单独的 ID。

一个示例实现在我的 github 存储库中 https://github.com/trajano/tomcat-docker-swarm

最新更新