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>/fail | 200 OK,记一次失败,186.9 毫秒 |
| GET /ping/全零 uuid | 404,路径里的 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 部署都没有验证,不作结论。










