Временные 503 ошибки после ./launcher rebuild appN при использовании HAProxy в качестве фронтенда

Я создал тестовый форум с двумя контейнерами web_only, контейнером mail-receiver, Postgres и Redis в одной Docker-сети. Два веб-контейнера с nginx были выведены через HAProxy. Они работали хорошо, но при пересборке одного из двух веб-контейнеров я всегда наблюдал небольшой простой, в течение которого возвращалась ошибка 503.

К счастью, я нашел обходное решение, хотя оно и не идеальное;


перед пересборкой app1 выполните

echo "disable server be_discourse/app1" | socat stdio /run/haproxy/admin.sock

а после завершения процесса пересборки app1 выполните

echo "enable server be_discourse/app1" | socat stdio /run/haproxy/admin.sock

Аналогично, для пересборки app2 выполните

echo "disable server be_discourse/app2" | socat stdio /run/haproxy/admin.sock

а после завершения процесса пересборки app2 выполните

echo "enable server be_discourse/app2" | socat stdio /run/haproxy/admin.sock

это основано на соответствии /etc/haproxy/haproxy.cfg относительно be_discourse. Я пока не буду вставлять файл конфигурации в блок кода, но если наберется достаточное количество желающих, я это сделаю.

Таким образом, дополнительные команды предотвращают появление 503, сообщая HAProxy перенаправить трафик до того, как он обнаружит, что от неработающего контейнера будет возвращена ошибка 503.


В качестве альтернативы можно создать страницу ошибки, но у меня не очень хорошо получилось с этим, и я считаю, что здесь нужны дополнительные исследования. Однако это не решает проблему простоя.

Почему бы вам не перенаправить redispatch запрос на следующий сервер при получении ответа 503?

Отлично! Это было бы хорошо. Также у вас есть какие-либо предложения по Sidekiq? Я вообще не вижу Sidekiq в discourse_docker/samples at main · discourse/discourse_docker · GitHub, что привело меня к внесению следующих изменений в один из файлов yml


app1.yml

## Помните, это синтаксис YAML — у вас может быть только один блок с именем
run:
  - exec: echo "Начало пользовательских команд"
+  - exec: rm -f /etc/service/sidekiq/down
  ## Если вы хотите настроить вход под root по паролю, раскомментируйте и измените:

app2.yml

## Помните, это синтаксис YAML — у вас может быть только один блок с именем
run:
  - exec: echo "Начало пользовательских команд"
+  - exec: bash -lc 'mkdir -p /etc/service/sidekiq && touch /etc/service/sidekiq/down'
  ## Если вы хотите настроить вход под root по паролю, раскомментируйте и измените:

Для тех, кто запускает несколько веб-контейнеров, стоит подумать ещё об одном моменте: где именно запускается Sidekiq.

Ошибки 503 влияют только на веб-запросы, но если Sidekiq остановлен, ваш сайт перестанет обрабатывать фоновые задачи (письма, дайджесты, бейджи, вебхуки) без каких-либо явных сигналов. Удобный способ решения — выделить Sidekiq в отдельный контейнер и отключить его на веб-узлах.

Discourse использует runit под капотом: каждый сервис в /etc/service/* запускается, если внутри его директории нет файла с именем down. Этого достаточно для управления.

Вот пример конфигурации отдельного воркера Sidekiq:

worker.yml — только Sidekiq
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"

expose: []   # нет HTTP-портов

env:
  DISCOURSE_DB_HOST: data
  DISCOURSE_REDIS_HOST: data
  DISCOURSE_HOSTNAME: "forum.example.com"
  # согласуйте с вашими существующими секретами / настройками SMTP

hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          # отключаем веб-сервисы
          - mkdir -p /etc/service/puma  && touch /etc/service/puma/down
          - mkdir -p /etc/service/nginx && touch /etc/service/nginx/down
          # включаем Sidekiq
          - rm -f /etc/service/sidekiq/down

run:
  - exec: echo "Запуск контейнера воркера Sidekiq"

На веб-контейнерах (app1/app2) следует сделать наоборот — оставить Puma и Nginx включёнными, но добавить:

hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          - mkdir -p /etc/service/sidekiq && touch /etc/service/sidekiq/down

С такой настройкой HAProxy балансирует нагрузку только между веб-контейнерами, а Sidekiq продолжает работать в контейнере воркера (.\launcher rebuild <имя_yml>). Таким образом, фоновые задачи не будут прерываться при пересборке или ротации ваших веб-узлов.

Я перенёс это в #installation:hosting, так как, похоже, это бесконечное обсуждение. Давайте избегать создания таких тем в Support.