Skip to content

可观测性与运维

本页讲Molore云端的可观测性设施与运维纪律:自动运营日报、检索健康度指标、生产安全面(文档端点关闭、安全头、限流)、内存安全网与 pm2 部署纪律,以及「查库比翻日志快」的排障口径。目标是在单台小机上把服务跑稳,并且出问题时能按固定顺序快速定位。

概念

概念说明
自动日报每天 08:30(CST)生成昨日运营日报,落 daily_reports
检索健康度按日聚合的检索指标表 retrieval_metrics_daily,观察检索通道退化
生产安全面生产环境关闭 API 文档端点、发安全响应头、按 IP 分桶限流
内存安全网常驻模型上限 + earlyoom + pm2 内存重启帽三件套
部署探针重启后核对文件 mtime + 内容级断言(不看状态码)

功能清单

  • 自动日报:app/services/daily_report.py,apscheduler 每天 08:30(CST)触发,默认统计昨日(UTC);Markdown 分段生成,单段失败只影响该段(段内异常降级为「该段数据异常」占位,不拖垮整份日报)。
  • 检索健康度:app/models/metrics.pyRetrievalMetricsDailyday+metric 复合主键,按 UTC 日聚合),app/services/retrieval_metrics.py 提供 incr(metric, n) 计数入口,检索链路各通道打点,用于按日观察通道开火与退化。
  • 生产关闭文档端点:app/main.pydocs_url=None if _is_prod else "/docs"/redoc/openapi.json 同口径——生产不暴露 API 结构。
  • 安全响应头(app/core/security_middleware.py):HSTS(max-age=31536000; includeSubDomains)、CSP(CSP_ENABLED 开关,策略串只对 document 生效)、X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-PolicyPermissions-Policy
  • 限流带 Retry-After:四类桶均返回 429 + Retry-After: 60
  • 内存安全网三件套:Ollama 常驻模型数压到 1(MAX_LOADED_MODELS=1)、系统级 earlyoom 兜底、pm2 --max-memory-restart 1400M
  • 失败定位走数据库:图谱构建失败原因在 graph_build_state.error(500 字截断),CLI 逐 chunk 错误不进 pm2 日志——查库比翻日志快。

限流口径

按 IP 分桶,客户端 IP 取值规则(security_middleware._get_client_ip):请求来源在 TRUSTED_PROXY_IPS 内时取 X-Forwarded-For末段(末段由可信代理写入、客户端无法伪造;取首段等于让攻击者自选限流 key)。不配 TRUSTED_PROXY_IPS 时全站共享 127.0.0.1 一个桶

生产限额适用范围
login_limiter5/min/api/v1/auth/login/api/admin/auth/login、注册
chat_limiter30/min/api/v1/llm/chat/summarize/extract-tags
admin_limiter200/min/api/admin/
api_limiter100/min(桌面端 600/min)其余 /api/

桌面端(PSB_DESKTOP=1)是本机单用户形态、所有请求共享 127.0.0.1 一个桶,通用限流放宽到 600/min(批量删除 100 条素材曾把桌面端自己 429 到「掉线」)。

内存安全网

小机部署先算「所有同时在场者」的内存总账(血泪#53/#88):

组件配置作用
Ollama 常驻模型MAX_LOADED_MODELS=1同时只驻留一个模型,压住常驻内存
earlyoom系统级守护内存耗尽前杀进程兜底
pm2 重启帽--max-memory-restart 1400M主进程超帽自动重启

关键教训:内存帽要按「基线 + 请求峰值」配,基线贴帽等于每个请求都是重启抽奖。曾以 780MB 基线配 800M 帽导致连环重启全站 502;根治手段是重型可选依赖(numba/UMAP)计算子进程化,峰值随子进程退出即释放,主进程基线 780→413MB,当前帽 1400M 余量充足。pm2 内存杀在应用日志里无痕,实证看 ~/.pm2/pm2.log 的 "exceeds --max-memory-restart"。

pm2 部署纪律

  • 进程形态:pm2 start bash --name grzhishiku --max-memory-restart 1400M -- -c '.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8080',nginx 443 反代,pm2 save 固化。
  • 后端发布:tar 含 app/--exclude __pycache__)→ pip install -r requirements.txtpm2 restarttar 覆盖解压不删旧文件,拆包/删文件的批次必须显式 rm 旧文件(血泪#75)。
  • 前端发布:tar 在 dist 内部打包(无前缀),mv 整体换新。
  • 重启后必核文件 mtime + 内容级探针:只看状态码会被 SPA fallback 的 200 骗过;探针定串用纯文本(grep -cF),别带反斜杠(经双层 shell 漏成字面量造成假 FAIL,#97)。
  • 大文件传输:scp 分片 10MB + 重试 + sha256 双端校验,一个时刻只跑一个上传。

排障顺序

502 先看进程在不在,别先怀疑代码(#56):

  1. /health 探活;
  2. pm2 uptime/restarts 看进程状态与重启次数;
  3. 端点重试;
  4. 最后才翻日志。

构建类失败直接查库:SELECT error FROM graph_build_state ... 拿失败原因(500 字截断),比翻 pm2 日志快——CLI 逐 chunk 错误不进 pm2 日志(生产实捕)。

下一步

基于 AGPL-3.0 协议发布。