HAProxy 前置时的瞬时 503 错误

我创建了一个测试论坛,其中包含两个 web_only 容器、一个 mail-receiver 容器、Postgres 和 Redis,它们都在 Docker 网络上。两个 Web 容器 nginx 都由 HAProxy 提供前端服务。它们运行良好,但我发现在重建两个 Web 容器之一时,总会有短暂的停机时间,并返回 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/app1” | socat stdio /run/haproxy/admin.sock


这基于 /etc/haproxy/haproxy.cfg 中与 be_discourse 匹配,我暂时不会将配置文件粘贴到代码块中,但如果大多数人都想要,我可能会这样做。

因此,这通过告知 HAProxy 在容器出现 503 错误之前将流量转移来缓解 503 错误。


你也可以创建一个错误页面,但我对此不太成功,并且觉得需要进一步研究。但是,这并没有真正解决停机问题。

为什么不在出现 503 时重新分发到下一台服务器?

1 个赞

太好了!那会很好。另外,您对 sidekiq 有什么建议吗?我在 discourse_docker/samples at main · discourse/discourse_docker · GitHub 中完全看不到 sidekiq,这导致我对手动更改 yml 文件进行了以下更改:


app1.yml

## 记住,这是 YAML 语法 - 您只能有一个名为的块
run:
  - exec: echo "Beginning of custom commands"
+  - exec: rm -f /etc/service/sidekiq/down
  ## 如果您想为 root 配置密码登录,请取消注释并更改:

app2.yml

## 记住,这是 YAML 语法 - 您只能有一个名为的块
run:
  - exec: echo "Beginning of custom commands"
+  - exec: bash -lc 'mkdir -p /etc/service/sidekiq && touch /etc/service/sidekiq/down'
  ## 如果您想为 root 配置密码登录,请取消注释并更改:

对于运行多个 Web 容器的任何人来说,还有一个额外的需要考虑的点是 Sidekiq 的运行位置

503 错误只会影响 Web 请求,但如果 Sidekiq 宕机,您的网站将悄无声息地停止处理后台作业(电子邮件、摘要、徽章、Webhooks)。处理此问题的一个巧妙方法是为 Sidekiq 分配自己的容器,并将其在 Web 节点上禁用。

Discourse 在底层使用 runit/etc/service/* 中的每个服务都会启动,除非在其目录中存在一个名为 down 的文件。这就是所需的全部控制。

以下是一个专用 Sidekiq worker 的示例:

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: []   # no HTTP ports
env:
  DISCOURSE_DB_HOST: data
  DISCOURSE_REDIS_HOST: data
  DISCOURSE_HOSTNAME: "forum.example.com"
  # match your existing secrets / SMTP settings
hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          # disable web services
          - mkdir -p /etc/service/puma && touch /etc/service/puma/down
          - mkdir -p /etc/service/nginx && touch /etc/service/nginx/down
          # enable Sidekiq
          - rm -f /etc/service/sidekiq/down
run:
  - exec: echo "Starting Sidekiq worker container"

在 Web 容器(app1/app2)上,应执行相反的操作 - 保持 Puma 和 Nginx 启用,但添加:

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

通过这种设置,HAProxy 只负责平衡 Web 容器,而 Sidekiq 则在 worker 中继续运行。这样,当您重建或轮换 Web 节点时,后台作业不会中断。

我已将此移至 Installation > Hosting,因为它似乎是一个开放式对话。让我们避免在 Support 中创建此类对话。

1 个赞