Sticky Sessions с роем докеров

У меня есть докеризованное приложение node.js, которое использует socket.io

С помощью docker compose я запускаю 2 реплики приложения в двух разных контейнерах на одном сервере. Однако запросы, поступающие на серверы, распределяются циклическим образом.

Есть ли способ, который я могу использовать для достижения липких сессий?

мой docker-compose.yml выглядит так:

version: '3'

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

и я использую развертывание стека докеров для запуска двух реплик приложения.


person Ahmed Ghazy    schedule 28.01.2019    source источник


Ответы (2)


Насколько я понимаю, существует 3 возможных варианта реализации сходства сеансов в Docker или Docker Swarm.

<сильный>1. Добавьте метки, чтобы установить закрепленный сеанс, что является очень простым и официальным способом, если вы используете Docker Enterprise Edition.

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/;
        }
    }
}
person Dashzeveg Galbadrakh    schedule 04.01.2021
comment
Вам нужно добавить ip_hash, чтобы сделать nginx липким http://nginx.org/en/docs/http/load_balancing.html#nginx_load_balancing_with_ip_hash - person MortenF; 04.03.2021

Я думаю, что вы ищете этот документ, описывающий различные подходы для сохранения сеанса при использовании Docker Swarm.

В частности, вы можете настроить фиксированную сессию на основе файлов cookie или IP-хеширования.

Согласно онлайн-документации, похоже, вам нужно добавить следующие метки в вашу конфигурацию:

labels:
   - "com.docker.lb.hosts=demo.local"
   - "com.docker.lb.sticky_session_cookie=session" 
   - "com.docker.lb.port=3001"
person dongi    schedule 28.01.2019
comment
Я попытался добавить эти строки, а также запустить службу, как указано в документе, но все равно ничего не работает. Разница, я думаю, заключается в том, что в примере служба представляет собой nginx, а в моем случае это приложение node.js. - person Ahmed Ghazy; 28.01.2019
comment
Для этого вам нужно использовать Docker Swarm и включить его маршрутизацию уровня 7. Как только вы установите его на место, он должен работать. - person dongi; 28.01.2019
comment
Документация предназначена для Docker EE; кто-нибудь знает, не повезло ли Docker CE? - person Foon; 15.05.2020
comment
Да, этот подход работает только для EE. Это не будет работать для CE. - person Andy Madge; 21.02.2021