Healthchecks 是给定时任务看的监控服务:脚本跑完往一个地址发个请求,到点没收到就告警。它是 Python 写的 Django 应用,数据库可以只用 SQLite。这篇在 Windows 上从装依赖走到发 ping、翻故障状态,把每一步的真实返回记下来。

装依赖只卡了一个包

Python           3.13.12(独立 venv,放在 D 盘)
Django           5.2.4
pycurl           7.48.0(17.3 MB,下载用了 5 分 13 秒)
其余依赖        cronsim / fido2 / pyotp / django-compressor 已在位

requirement 里列了十几个包,实际只缺 pycurl 一个。它是 C 扩展,装的时候必须用预编译好的 wheel,加 --only-binary=:all: 能避免 pip 去找编译器。17.3 MB 走了五分多钟,瓶颈在网络上不在编译。

迁移建出 24 张表

python manage.py migrate --noinput
最后几条      payments.0006 → 0009 AlterSubscription_user → sessions.0001 OK
数据库        hc.sqlite
体积          339,968 字节
表数量        24 张

默认落 SQLite,一个文件就是整个服务的数据。24 张表里跟监控直接相关的只有几张:api_check 存检查,api_ping 存每次心跳,api_flip 存状态翻转。剩下的多是无障碍登录、支付订阅这些模块带来的表。

3.11 版先建项目,检查收在项目里

登录后首页不再是检查列表,而是一屏项目卡片。点 New Project 填个名字,进去才看到 CHECKS、INTEGRATIONS、BADGES、SETTINGS 四个标签页。项目名就是以后看板上的分组,一个人用建一个项目就够了。

界面位置作用
Projects 首页项目卡片,右侧 New Project 建新组
CHECKS 标签检查列表,右上角 Add Check 弹窗
INTEGRATIONS邮件、Slack、Webhook 等告警通道
BADGES生成状态徽章,可贴到 README

登录表单认的是邮箱,不是用户名。用 createsuperuser 建号时填的邮箱才是登录凭据,输用户名会一直提示密码错误。

建检查只要填名字

弹窗字段    name / slug / tags / kind / timeout / grace / tz
本次填的    name=订单服务心跳,其余留默认
kind        simple(简单心跳)
timeout     86,400,000,000 微秒(界面显示 Period 1 day)
grace       3,600,000,000 微秒(界面显示 Grace 1 hour)

类型默认就是 simple:到点没收到请求就算异常。另一类是 cron,要写类似 */5 * * * * 的表达式,服务按表达式去推算下次该来的时间。超时和宽限在列表里显示成 1 day 与 1 hour,数据库里存的是微秒数,两者差 86400 倍,看库的时候别当成秒。

ping 一下返回 OK,中位 183.6 毫秒

GET /ping/44d3bc10-8cd2-4a70-9efc-0338de647ca4
返回        200 OK,正文 OK
五次延迟    170.2 / 176.9 / 183.6 / 198.4 / 205.5 毫秒
中位数      183.6 毫秒
带 rtt 参数 200 OK,查询串写成 ?rtt=127 会记录耗时

这个延迟是 Django 开发服务器加 SQLite 写一次的结果,换 gunicorn 会低不少。地址里的 UUID 必须带横线,用数据库里那串无横线的 32 位十六进制去请求会直接 404。第一次 ping 之后列表里的 Last Ping 从 Never 变成 now。

报一次 fail,状态就翻成 down

动作结果
GET /ping/<uuid>200 OK,记一次成功
GET /ping/<uuid>/fail200 OK,记一次失败,186.9 毫秒
GET /ping/全零 uuid404,路径里的 UUID 不存在
连续 fail 之后查库status 从 new 变成 down

实测跑完后 api_ping 累计 12 条,api_flip 累计 6 条,检查状态落在 down。翻转记录比心跳多说明状态在正常与异常之间来回跳,每次翻转单独存一行,排查抖动时看这张表最直接。

复制出来的地址是 localhost:8000

页面显示  http://localhost:8000/ping/44d3bc10-...
实际端口  127.0.0.1:8021
原因      没设 SITE_ROOT,服务用默认值拼 URL

这个坑第一次用就会遇到:检查建好之后复制出来的 Ping URL 永远指向 8000 端口,跟实际监听端口无关。要让地址可用,启动前把 SITE_ROOT 环境变量设成真实地址,比如 http://127.0.0.1:8021。不改也能测,手工换掉端口即可,但真放到服务器上给脚本用时必须改对,否则脚本会把心跳打到别处。

实测范围:Windows 10 22H2(10.0.19045.6466) / healthchecks 3.11 / Django 5.2.4 + SQLite / 2026-10-22。邮件与 Webhook 告警、cron 表达式检查、多人协作、HTTPS 部署都没有验证,不作结论。