Skip to content

生产可观测性与故障 Runbook ​

本页覆盖生产观测入口、Prometheus/告警配置,以及常见故障的分步处置。 每条告警的 runbook 注解都指向本页对应小节或 deploy/monitoring/runbooks/*.md。

观测入口 ​

入口用途
/healthz经过 Nginx 的就绪探针(转发到 core 的 /health/ready);返回 503 时不应继续导入流量
core:8000/health/live进程存活检查,不检查外部依赖
core:8000/health/ready检查 PostgreSQL、Redis 与结果消费者,critical 探针全 up 才 200
core:8000/metricsPrometheus 指标端点,只应在内部网络抓取,不应映射到公网

/healthz 不返回依赖明细

/healthz 经 Nginx 暴露且无鉴权,因此生产环境不返回依赖明细;调试请直连 core:8000/health/ready。旧综合端点 /health 始终返回 200 + healthy/degraded。

Prometheus 与告警 ​

对象存储盘点不是 core 请求路径的一部分。按日运行:

bash
cd noj-core
deno task storage:audit -- --prometheus-output <textfile-dir>/noj_storage.prom

通过 textfile collector 观察 noj_storage_objects_total、noj_storage_bytes、 noj_storage_orphan_objects、noj_storage_orphan_bytes 和 noj_storage_missing_references 的趋势。该命令只读,不会删除对象;治理边界与复核 步骤见对象存储生命周期治理。

将 Prometheus 加入 noj-net,使用 deploy/monitoring/prometheus.yml 抓取 core:8000 与 llm-gateway:8001(前者含 up{job="noj-core"} 失联检测; 目标名必须与 compose 服务名一致),并加载两个规则文件:

  • deploy/monitoring/noj-alerts.yml:运维告警,手工维护;
  • deploy/monitoring/noj-slo-alerts.yml:SLO 燃烧率告警,由 noj-core/src/domains/observability/slo.ts 经 scripts/gen-alert-rules.ts 生成,勿手工编辑。

Alertmanager 配置模板、凭据注入与投递演练见 deploy/monitoring/README.md。 Grafana 可导入 deploy/monitoring/grafana-dashboard.json。通知接收器凭据应保存在 部署环境,不提交到仓库。

第二个规则文件缺失不会报错。 Prometheus 的 rule_files 指向不存在的文件时照常启动, 只是整组 SLO 规则静默消失。安装后必须用 promtool check config 校验,并确认 /rules 页面同时列出 noj-production 与 noj-slo 两组;NojSloRulesMissing 告警是这一丢失的看门狗。

SLO 告警分两族:NojSlo<名称>Fast(severity 由 SLO 定义,短保持时长)与 NojSlo<名称>Slow(warning,长保持时长)。当前为单窗口燃烧率——burn_rate > 1 等价于 在 SLI 自身窗口内 SLI < objective,因此 Fast 会被 Slow 严格蕴含;解析告警敏感度时应以 SLI 表达式里的窗口为准,而不是 Slow 的长窗口。每个 SLO 的处理步骤见其 runbook 注解指向的 deploy/monitoring/runbooks/*.md。

每次发布后应确认 Prometheus target 为 UP、live/ready/metrics 可以访问,并在 staging 演练一次 Judge 或 Redis 故障及其恢复。上线前必须执行一次告警投递演练(见 deploy/monitoring/README.md §5, 不再提供 scripts/deploy/test-alert.sh)并记录结果。

社区搜索性能 ​

社区题解和讨论搜索保留 ILIKE '%关键词%' 子串语义。生产 PostgreSQL 通过迁移追加标题和正文的 pg_trgm GIN 部分索引;pg_trgm 扩展由迁移 0017 与 0070 先后以 CREATE EXTENSION IF NOT EXISTS 启用(前者用于搜索索引,后者为社区 ILIKE 子串搜索),不能回改历史迁移。PGlite 测试环境未内置该扩展, 测试 DDL 会检测能力后跳过对应索引,但不影响生产迁移。

搜索路由限制关键词为 2~100 个字符。短关键词、高命中率关键词或统计信息不足时,PostgreSQL 仍可能合理选择 Seq Scan;容量验收应使用约 10 万行代表性数据记录 EXPLAIN (ANALYZE, BUFFERS)、P50/P95 和索引体积, 不能要求所有输入强制走 trigram 索引。

常见故障 ​

Core 失联 ​

触发:NojCoreScrapeDown(抓取失败)、NojCoreMetricsMissing(序列缺失)。

  1. noj-cli status 与 docker logs 确认 core 容器状态;区分进程退出与网络/抓取配置问题。
  2. 查看 noj-cli logs core 中的启动顺序错误(JWT_SECRET、迁移、Redis)。
  3. 恢复后确认 Prometheus target UP,且 noj_database_up、noj_redis_up、 noj_result_consumer_up 恢复为 1。
  4. 若 core 失联期间发生评测,恢复后确认 pending 队列回落,必要时检查 NojQueueBacklog* 告警是否解除。

PostgreSQL / Redis 异常 ​

触发:NojDatabaseUnavailable、NojRedisUnavailable。

  1. 先查看 /health/ready 与 noj-cli logs core,确认是依赖不可达还是健康检查超时。
  2. docker compose ps 检查 postgres/redis 容器与健康状态;查看容器日志定位 OOM/磁盘/密码问题。
  3. 恢复依赖后确认队列逐步回落;Redis 数据卷损坏时使用最近快照恢复(见生产部署文档 5.1 节)。
  4. 不要直接删除 Redis 数据卷或队列(包括 FLUSHDB/FLUSHALL)。

评测结果消费者异常 ​

触发:NojResultConsumerDown、NojResultQueueBacklog。

  1. noj-cli logs core 查找结果消费者启动与写入错误;确认 PostgreSQL 可写。
  2. results processing 积压通常是数据库写入失败重试:先恢复数据库,再观察积压回落。
  3. 消费者重启后确认 noj_result_consumer_up == 1 且积压清零。

Judge Worker 异常 ​

触发:NojJudgeWorkersDown、NojJudgeHeartbeatMissing。

  1. 检查 Worker 心跳、活跃任务和 noj-cli logs judge;确认独立 rootless Docker daemon 可用。
  2. NojJudgeHeartbeatMissing 通常伴随 core 失联:先按 Core 失联处理。
  3. 恢复后确认心跳指标恢复且队列开始消费;不要直接删除 Redis 数据卷或队列。

评测队列堆积 ​

触发:NojQueueBacklogWarning、NojQueueBacklogCritical。

  1. 确认 Judge Worker 在线且吞吐正常(见 Judge Worker 异常)。
  2. 评估是否为提交洪峰:必要时暂停新评测入口,扩容 Worker 后恢复。
  3. 观察磁盘与缓存压力,避免 Worker 因资源不足批量失败。
  4. 恢复后确认队列回落,且无新的 NojStaleJudging 触发。

NojStaleJudging(评测卡死)的处置步骤见 deploy/monitoring/runbooks/queue-oldest-judging-age.md——该告警的 runbook 注解已 指向那里,此处不再重复,避免同一故障存在两份可能漂移的处置说明。

API 错误率或延迟升高 ​

触发:NojApiErrorRateRecentWarning、NojApiErrorRateRecentCritical(5 分钟滑动窗口 5xx 比例)、 NojApiLatencyHigh(P95)。

  1. 按路由与状态码查询结构化日志,区分依赖异常、慢查询和限流。
  2. 结合 noj_database_up / noj_redis_up 判断是否为依赖故障传导。
  3. 恢复后确认 5 分钟窗口错误率回落:sum(rate(noj_http_request_errors_total[5m])) / sum(rate(noj_http_requests_total[5m]))。

磁盘和缓存压力 ​

触发:NojJudgeWorkDirPressure、NojHostDiskLow。

  1. 优先暂停新评测、保留备份和日志,再扩容或按缓存策略清理。
  2. 不得直接删除数据库、Redis 或对象存储卷(包括 FLUSHDB/FLUSHALL)。
  3. 处理后确认 node_filesystem_avail_bytes 比例回升。

备份过期 ​

触发:NojBackupStale(>25h)、NojBackupVeryStale(>49h)、NojBackupMetricMissing。

  1. 检查备份 cron 是否运行、noj-cli backup create 最近输出与退出码。
  2. 确认 textfile 目录(<备份目录>/metrics/noj_backup.prom)在最近一次备份后有更新; NojBackupMetricMissing 通常说明 node_exporter textfile collector 未配置(见 deploy/monitoring/README.md 第 4 节「node_exporter 与备份新鲜度指标」)。
  3. 备份长时间未成功期间发生的故障无法回滚,尽快手动执行一次备份并验证。

恢复演练过期 ​

触发:NojRestoreDrillStale(>90 天未演练)。

  1. 文件校验不能证明业务可恢复;安排执行 noj-cli backup drill <快照>(见生产部署文档 5.1 节)。
  2. 演练完成后确认 textfile 目录中 noj_restore_drill.prom 更新,告警在下一个评估周期解除。

先把 Prometheus 接上再谈告警

最省事的方式是用 compose 的 monitoring profile 一键拉起 Prometheus + Alertmanager:

bash
docker compose --env-file .env.prod -f docker-compose.prod.yml --profile monitoring up -d

启动前须把 deploy/monitoring/alertmanager.yml.example 复制为 deploy/monitoring/alertmanager.yml 并填入接收器(否则 Alertmanager 会 fail-fast)。详见 deploy/monitoring/README.md。

Neuro OJ 是一个独立社区项目,与 CCF、LMCC、IOAI 及 NOAI 无官方关系。