您可以在没有前端的情况下执行此操作,但是您会遇到问题,因为如果入口路由到不同的节点,则该节点必须从另一个节点请求会话。
普通的 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 不添加额外组件的要求,但会出现严重的性能问题。相反,您需要一个可以路由到具有以下功能的服务器的代理:
- 会话粘性
- Docker Swarm 服务标签发现
- 通过提前检测服务器停机来减少潜在用户影响的运行状况检查。
Traefik 可以很好地处理所有要求,即使它本身不支持集群 due to their ACME storage not allowing concurrent access 而无需转到其 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 repo https://github.com/trajano/tomcat-docker-swarm 中有一个示例实现