【问题标题】:Sticky Sessions with docker swarm与 docker swarm 的粘性会话
【发布时间】:2019-06-21 12:41:46
【问题描述】:

我有一个使用 socket.io 的 dockerized node.js 应用程序

通过 docker compose,我在同一服务器上的两个不同容器上为应用程序运行 2 个副本。然而,到达服务器的请求是以循环方式分发的。

有什么方法可以用来实现粘性会话吗?

我的 docker-compose.yml 如下所示

version: '3'

services:
 app:
   ports:
     - "3001:3001"
   image: image
   deploy:
     replicas: 2

我使用 docker stack deploy 来运行应用程序的两个副本

【问题讨论】:

    标签: node.js docker docker-compose docker-swarm sticky-session


    【解决方案1】:

    据我了解,在 Docker 或 Docker Swarm 上实现会话亲和性有 3 种可能的变体。

    1.添加标签以建立粘性会话,如果您使用的是 Docker 企业版,这是非常简单且官方的方法。

    labels:
       - "com.docker.lb.hosts=example.com"
       - "com.docker.lb.sticky_session_cookie=session" 
       - "com.docker.lb.port=3001"
    

    除非您购买了使用 Docker EE 的许可证,否则您需要使用以下两种方法之一。

    2。使用 Traefik 负载均衡器。 假设部署一个名为 app 的服务;容器部署在 192.168.0.1 和 192.168.0.2 是 Docker Swarm 中连接的节点。

    version: "3.8"
    
    services:
      traefik:
        image: traefik:v2.3
        deploy:
          mode: global
        networks:
          - traefik-net
        command:
          - "--log.level=DEBUG"
          - "--api.insecure=true"
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.app.address=:80"
        ports:
          - 3001:80
          - 8080:8080
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
      app:
        image: nginx
        deploy:
          replicas: 2
        networks:
          - traefik-net
        labels:
           - "traefik.enable=true"
           - "traefik.http.routers.app.entrypoints=app"
           - "traefik.http.routers.app.rule=Host(`192.168.0.1`) || Host(`192.168.0.2`)"
           - "traefik.http.services.app-service.loadBalancer.sticky.cookie=true"
           - "traefik.http.services.app-service.loadBalancer.sticky.cookie.name=app_cookie_name"
           - "traefik.http.services.app-service.loadbalancer.server.port=80"
        
    networks:
      traefik-net:
        external: true
        name: traefik-net
    

    3.使用 Nginx 反向代理。假设容器将部署在 192.168.0.1 和 192.168.0.2,它们是 Docker Swarm 中连接的节点。

    为了绕过路由网格,您需要使用一个副本部署两个服务(app1、app2),因为 Docker Swarm 的默认负载平衡方法是循环。

    version: "3.8"
    
    services:
     app1:
       ports:
         - "3001:3001"
       image: image
       deploy:
         replicas: 1
     app2:
       ports:
         - "3002:3001"
       image: image
       deploy:
         replicas: 1
    

    Nginx 配置: 由于 Docker Swarm 使用路由网格(循环负载均衡器),因此您需要注册每种方式来访问容器。

    http {
        upstream example {
            ip_hash;
            server 192.168.0.1:3001;
            server 192.168.0.1:3002;
            server 192.168.0.2:3001;
            server 192.168.0.2:3002;
        }
    
        server {
            listen          80;
            server_name     example.com;
        
            location / {
                proxy_pass http://example/;
            }
        }
    }
    

    【讨论】:

    【解决方案2】:

    我认为您正在寻找的是document,它描述了使用 Docker Swarm 时会话持久性的不同方法。

    特别是您可以配置基于 Cookie 或 IP 哈希的粘性会话。

    根据在线文档,您似乎需要在配置中添加以下标签:

    labels:
       - "com.docker.lb.hosts=demo.local"
       - "com.docker.lb.sticky_session_cookie=session" 
       - "com.docker.lb.port=3001"
    

    【讨论】:

    • 我尝试添加这些行并运行文档中提到的服务,但仍然没有任何效果。我猜的不同之处在于,在示例中,服务是 nginx,而在我的情况下,它是 node.js 应用程序
    • 为此,您需要使用 Docker Swarm 并启用 Layer 7 Routing。安装到位后,它应该可以工作了。
    • 文档适用于 Docker EE;有人知道 Docker CE 是不是运气不好?
    • 是的,这种方法仅适用于 EE。它不适用于 CE。
    猜你喜欢
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 2018-05-19
    相关资源
    最近更新 更多