告警是一个讲究细节的游戏。没有人会因为自己的意图被呼叫——他们是因为写下的那条具体查询被呼叫。如果你想安稳睡一整夜,查询必须表达出你以为它表达的意思,而大多数时候,你是在凌晨三点才发现它并没有。
我见过最清晰的例子甚至算不上微妙。一位同事为我们的文件处理器设置了一个消息处理数量的告警,作为吞吐量信号。这看起来完全合理——如果一条消息就是一个工作单元的话。但它不是。一条消息携带最多十个URL的批次,而我们真正关心的是PDF下载。
![]()
关键在于,这并非有意的近似。没有人权衡过按下载次数计量的成本,然后选择消息数作为更便宜的代理指标。一条消息包含多个URL这个细节,写规则的人根本不知道,所以从一开始就没有权衡可言。我们完全是在追踪错误的指标。
错误指标的连锁反应
下游的一切都继承了这个问题。阈值、SLO、几个月积累的"这个数字正常吗"的直觉——所有这些都悄悄以错误的单位计价。五条消息,二十六个工作单元,两者之间没有恒定比例。
这就是下面每一条经验教训的形状。指标本身没问题。从指标到意图的映射,才是出问题的地方。
经验一:下限告警无法区分"卡死"和"空闲"
明显的吞吐量告警是一个下限:少于N个项目在M分钟内,就呼叫。在夜间批处理工作负载上,这每晚都会触发,因为下限无法区分"卡住了"和"空闲,确实没有工作"。
最老排队消息的年龄没有这两个问题。如果没有排队,就没有东西会变老,所以安静时段自动静默。如果工作排队了但没有移动,年龄就会攀升——无论消费者崩溃了还是正常运行但不消费,年龄都会攀升,而存活检查完全会漏掉这种情况。
它还让你免于编造一个数字。"每分钟40条消息正常吗?"需要你有一个工作负载模型。"有什么东西在这里待了六个小时?"则基于队列自身的排空时间,你可以在评审中为它辩护。
同一天,同一个事件。下限告警在二十四小时内触发了十七个小时;年龄信号只触发了一次。
经验二:队列年龄告诉你工作没有排空,但不告诉你原因
队列年龄告诉你工作没有排空。它不告诉你为什么,而有两种截然不同的为什么:
- 消费者崩溃了,没有进程在拉取工作
- 消费者活着,但每个工作单元花费的时间比预期长得多
经验三:按单元截止时间区分两种故障模式
按单元截止时间可以回答这个问题——"是否有任何单个任务超过了N分钟?"——而有用的信号不是它是否触发,而是它触发了多少次。
两行中的告警完全相同。计数告诉你你处于哪种情况。
经验四:零容忍规则会把慢请求误报为故障
我们的API是第二种情况的干净版本。在两周的时间里,大约十个请求超过了10秒,其他一切都很快。两周流量中的十个请求不是故障,而10秒的零容忍规则会为那些慢但不坏的请求呼叫我们。所以截止时间被放到了超限真正罕见的地方——30秒——现在告警意味着"有东西卡住了"而不是"有东西慢了"。
这个区别,就是告警从噪音变成信号的关键。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.