在优化层的第二站,我们谈故障排查。LEANN 上边缘后,问题往往不在代码而在环境:内存被别的进程挤占、索引文件损坏、依赖版本漂移。
我们主张埋最少的指标,但每个都要能指路。下面给出一段健康检查,覆盖三个最常见根因。
def health_check(app): issues = [] if app.index.size == 0: issues.append('索引为空: 摄取可能失败') if app.mem_mb() > app.mem_budget_mb: issues.append('内存超预算: 可能被挤占或泄漏') if not app.rerank_ready(): issues.append('重排头未加载: 模型文件可能损坏') return issues or ['健康'] print(health_check(app_dummy := None) if False else '占位')
这段检查的价值在「可行动」:每条问题都对应一个下一步,而不是笼统的「系统异常」。我们见过团队只打「查询失败」日志,排查花了一整天。
监控还要有趋势。下面给出滑动窗口统计尾延迟,因为平均值会掩盖长尾卡顿。
def tail_latency(samples, p=95): s = sorted(samples) return s[min(len(s)-1, int(len(s) * p / 100))] batch = [12, 13, 11, 200, 12, 14, 13, 190, 12, 11] print('P95 延迟(ms):', tail_latency(batch, 95)) # 远高于均值
案例:平均值掩盖的卡顿
监控要落地,日志必须先结构化。散文本行日志机器难解析,出事时只能人肉翻。下面给出一段结构化日志封装,每条带字段而非散文。
import json, time def log_event(event, **fields): rec = {'ts': time.time(), 'event': event, **fields} print(json.dumps(rec, ensure_ascii=False)) log_event('query', latency_ms=12, tenant='t1', hit=True) log_event('health', issues=[])
结构化后,5.2 开头的 P95 统计可以直接从这些记录聚合,不必再埋点。我们主张日志字段固定、值可变:固定字段让下游告警规则稳定,可变值承载上下文。
另一处坑是「告警疲劳」:阈值太敏,半夜被无关波动吵醒,久了就忽略真告警。我们建议阈值按业务分位设,而非拍脑袋绝对值,并设静默窗口避免重复轰炸。
监控还要回答一个问题:什么时候该告警,什么时候该忍。过度灵敏的告警会在正常波动里误报,久而久之被静音,真出事反而听不见。我们主张告警绑定「业务影响」而非「系统指标」:内存到 90% 不一定告警,但 P95 连续超阈值且命中率下跌,就必须告警。指标是证据,业务影响才是决策依据。
另一块是容量规划。边缘设备内存和算力固定,监控数据应能反推「还能撑多久」。比如索引每天新增十万条,当前内存曲线外推到上限还有三十天,你就有窗口安排扩容或归档,而不是等 OOM 当晚救火。监控的终点不是「看见」,而是「提前行动」,这正是这一章和下一章安全合规能衔接的地方。
| 告警绑什么 | 结果 |
|---|---|
| 系统指标 | 误报疲劳 |
| 业务影响 | 精准响应 |
监控数据的留存周期也要想清楚。P95 延迟这类指标留太久占资源,留太短又看不到趋势。我们建议热数据短期高精度、冷数据降采样长期存,前者用于实时告警,后者用于容量规划。两类用途对精度的要求不同,分开存既省钱又不丢洞察。
故障排查还有个软技能:复现。很多「偶发」问题其实是条件下必现,只是你没找到那个条件。我们建议排查时先固定变量,再逐步放开,比盲目改代码效率高得多。可观测性给你的是证据,而证据要配方法才能变成结论。我们也见过团队把监控做成炫酷大屏却没人看,监控的价值不在展示而在触发行动,一条能直接跳到根因的告警胜过一堆好看的曲线。
最后说一个反直觉的点:有时候要故意制造可控的失败来校验监控系统本身。定期做故障演练,拔掉某个组件看告警是否真响、定位是否真准。很多监控平时绿油油,真出事却哑火,就是因为从没被验证过。监控系统和业务系统一样,要靠演练证明它真的在工作。把监控、健康检查、结构化日志放在一起,它们构成系统的神经系统:日志是末梢感受、检查是反射动作、指标是大脑判断,缺一块系统就瞎或瘫或傻。
监控系统的可信度,还来自「它自己也会被监控」。我们主张对监控组件本身做存活检测:采集进程是否还在、上报链路是否通、告警通道是否没被静默。一个没人监控的监控系统,失效时往往最安静,等你发现已是事故之后。所以请给监控再加一层监控,让「监控挂了」也能被报出来,形成闭环。
另外,排查培训值得单独做。再好的工具,用人不会用也白搭。我们建议定期拿真实故障做复盘,把「当时怎么一步步定位到根因」写成可复用的路径,新人照着练几次,比看十篇文档都管用。可观测性的最后一公里,是人真的会看、会判、会动。
还有一类隐蔽故障叫「慢性退化」:系统没崩,但质量逐周下滑,直到某天被用户投诉才被发现。平均值监控发现不了它,因为单日跌幅太小。应对方法是跟踪趋势斜率而非单点值,一旦发现命中率连续走低就预警。可观测性不仅要看「现在坏没坏」,更要看「是不是在变坏」,后者才是护航长期稳定的关键。
监控与排查的尽头,是让系统「会说话」。当指标、日志、健康检查三件套齐备,出事时系统自己就能指给你看问题在哪,而不是让人盲猜。这套神经系统健全了,边缘端的 LEANN 才真正配得上「生产可用」四个字,也才对得起前面五章花力气搭起来的架构。
本节可考核点:能解释「健康检查的每条都要可行动」为何重要,并说明为何要用 P95 而非平均值衡量体感。