bigywater.tech
Django · 136

Django 健康检查接口

健康检查看起来是最简单的接口,在 Django 里却会踩到前面几篇讲过的坑:ALLOWED_HOSTS、SSL 重定向、会话中间件。这篇用探针的真实视角请求一遍,再把存活与就绪分开,看数据库挂了会怎样。

400 / 301 / 200
普通视图作探针:Pod IP 作 Host / http / https + 正确 Host
0 次查询
放在 MIDDLEWARE 最前面的存活中间件
503 vs 200
数据库停掉后,就绪探针 503,存活探针仍 200

普通视图作探针会失败

实测 · 本机执行输出
  Host: 10.0.0.5(Pod IP),http      → 400 
  Host: example.com,http           → 301 https://example.com/healthz/
  Host: example.com,https          → 200

探针从集群内部访问,Host 通常是 Pod IP,协议是 http。前者违反 ALLOWED_HOSTS(第 122 篇),后者触发 SSL 重定向(第 121 篇)。也可以用 SECURE_REDIRECT_EXEMPT 豁免路径、把 Pod IP 加进 ALLOWED_HOSTS,这两种做法本文没有测。

存活探针:最前面的中间件

实测 · 本机执行输出
  Host: 10.0.0.5,http        → 200  响应 b'ok'  数据库查询 0 次  Set-Cookie: False
  Host: example.com,http     → 200  响应 b'ok'  数据库查询 0 次  Set-Cookie: False

它必须放在 MIDDLEWARE 的第一位,并且不要调用 request.get_host()。代价是它不走任何后续中间件,也就没有任何认证与日志。

就绪探针:检查依赖

实测 · 本机执行输出
  [数据库运行中]
  /ready/  → 200  {"ready": true}                              用时    53.7 ms
  /live/   → 200  ok                                           用时     0.1 ms
  [数据库已停止(端口拒绝连接)]
  /ready/  → 503  {"ready": false, "error": "OperationalError"} 用时    54.4 ms
  /live/   → 200  ok                                           用时     0.1 ms

存活探针回答「进程还活着吗」,不应当依赖数据库;就绪探针回答「能处理请求吗」,可以检查数据库。第一次请求 /ready/ 要新建数据库连接,所以耗时远高于 /live/。

数据库不可达时

实测 · 本机执行输出
  /ready/ → 503  {"ready": false, "error": "OperationalError"}  用时 2053 ms

给探针里的数据库连接设置 connect_timeout,让它在探针自己的超时之内失败。

分步演示

健康检查
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。自己起的临时 PostgreSQL 16;用 Client 模拟探针(HTTP_HOST、secure);数据库停止用 pg_ctl;不可达地址用 10.255.255.1
    • 没有验证:Kubernetes 的真实探针配置(超时、失败阈值)、负载均衡器的健康检查行为、没有 connect_timeout 时的挂起时长、探针对缓存 / 消息队列等其它依赖的检查
    京ICP备2026067502号-1京公网安备11010502063487号