在 Django 应用程序中使用 HAProxy 和 uWSGI 执行第 7 层健康检查

Performing layer 7 health check with HAProxy and uWSGI in Django application

我正在使用这个 uwsgi.ini 来 运行 一个 Django 应用程序。

[uwsgi]
http-socket = :8000
enable-proxy-protocol = true
chdir = /usr/local/src/api
module = api.wsgi
uid = root
gid = root
pidfile = /var/run/api-uwsgi.pid
master = true
processes = 10
chmod-socket = 664
threaded-logger = true
logto = /var/log/api/uwsgi.log
log-maxsize = 10000000
logfile-chown = true
vacuum = true
die-on-term = true

我添加了 API url 以在 /health-check url 下执行数据库和缓存健康检查。这个 API returns 状态代码 200 如果一切正常。现在我希望能够使用此 API 和 HAProxy 在第 7 层进行健康检查,但使用 option httpchk 响应状态代码为 301,因此健康检查失败。这是我的 HAProxy 配置的后端部分。

backend http_server
  mode http
  balance leastconn
  option forwardfor
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
  option httpchk
  http-check send meth GET uri /health-check ver HTTP/1.1 hdr Accept application\json
  http-check expect rstatus 200
  server app1 192.168.0.11:8000 check inter 500 downinter 5s fall 2 rise 3
  server app2 192.168.0.12:8000 check inter 500 downinter 5s fall 2 rise 3

这是 运行 使用 uWSGIHAProxy 连接 Django 应用程序的结果。请注意,第 4 层的健康检查按预期工作。

Server http_server/app2 is DOWN, reason: Layer7 wrong status, code: 301, info: "Moved Permanently", check duration: 54ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.

那么是什么导致了这个问题,有没有办法解决它?

解决这个问题有两个步骤:

  1. 如果没有 url 路由与请求的 DjangoAPPEND_SLASH 设置相匹配,则在 url 的末尾附加一个 / 并执行一个 301 重定向。我使用 /health-check 而不是 /health-check/ 所以请求从 /health-check 重定向到 /health-check/
  2. http-checkhdr 选项接受键和值。对于 accept header 值必须在引号内,因此 hdr Accept application\json 变为 hdr accept "application/json"

这是后端配置的最终工作部分:

backend http_server
  mode http
  balance leastconn
  option forwardfor
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
  option httpchk
  http-check send meth GET uri /health-check/ ver HTTP/1.1 hdr accept "application/json"
  http-check expect rstatus 200
  server 192.168.0.11:8000 check inter 500 downinter 2s fall 2 rise 3
  server 192.168.0.12:8000 check inter 500 downinter 2s fall 2 rise 3