一、传统SkyWalking告警的痛点:为啥老告警不准?

做过线上服务监控的人,大概率都踩过SkyWalking告警的坑。比如半夜突然收到“慢查询告警”,打开监控一看,那个接口的响应时间才比平时慢了50毫秒,根本不影响业务;或者平时运行很稳的接口,某天突然有几个请求慢了,告警直接弹了,搞得人以为出大问题,结果查半天啥事儿没有。

其实问题出在传统的告警规则上。传统SkyWalking的告警是“定死的阈值”,比如你给某个接口设了“响应时间超过1秒就告警”,但这个接口的响应时间是跟着业务波动的——比如早高峰的时候,接口本来就会比平时慢30%,定死1秒的话,早高峰肯定天天告警;半夜流量少的时候,接口本来就快,偶尔慢到1秒就是真有问题,但传统规则也只会弹,没法区分场景。

还有就是“统计窗口”的问题,传统规则一般是固定时长的窗口,比如“连续3次响应时间超过1秒就告警”,但如果是突发的流量尖峰导致的偶尔慢请求,或者网络抖动的单次慢请求,根本不该告警,但传统规则识别不出来,只会机械触发。

二、核心思路:用动态阈值+滑动窗口解决问题

要让告警变准,核心就是解决两个问题:一是“什么时候算真的慢/错”,二是“怎么排除偶然情况”。对应的就是两个技术:动态阈值和滑动窗口。

2.1 动态阈值:让告警“跟着业务走”

动态阈值不是定死一个数,而是根据接口过去一段时间的运行数据,算出一个合理的“参考范围”,只有当当前数据超出这个范围太多的时候,才告警。比如一个接口平时的响应时间大多在200-500毫秒之间,那阈值就可以设成“平时的平均响应时间加2倍标准差”——如果平均是300毫秒,标准差是50毫秒,那阈值就是400毫秒;如果早高峰平均变成400毫秒,标准差变成100毫秒,阈值就自动变成600毫秒,这样就不会误报。

2.2 滑动窗口:避免偶然情况误报

滑动窗口的作用是“统计一段时间内的连续异常情况”,而不是单次异常就告警。比如我们可以设一个5分钟的滑动窗口,每1分钟统计一次这个窗口内的慢请求占比,只有当连续3次统计的占比都超过10%的时候,才告警。这样就能排除单次网络抖动、单次数据库锁导致的偶然慢请求,只有持续的问题才会触发告警。

三、具体配置:SkyWalking的规则怎么写?

SkyWalking的告警规则是用YAML格式写的,我们先明确整个配置的逻辑:先定义动态阈值的计算规则,再定义滑动窗口的统计规则,最后把这两个规则结合起来,触发告警。

3.1 先明确技术栈

所有配置基于SkyWalking 9.x版本(目前最常用的稳定版),技术栈统一为:SkyWalking 9.x + SkyWalking OAP(后端核心服务)。

3.2 动态阈值的实现

SkyWalking的OAP内置了统计函数,比如avg(平均)、stddev(标准差),我们可以用这些函数来计算动态阈值。比如我们要给一个叫“/api/user/info”的接口设置动态慢查询阈值,规则可以写成:

# 动态阈值计算:取过去1小时的平均响应时间 + 2倍标准差
threshold: avg(response_time, 1h) + 2 * stddev(response_time, 1h)

这里的response_time是SkyWalking收集的接口响应时间指标,1h是统计的时间范围,2倍标准差是行业内常用的“异常范围”——超出这个范围的话,大概率是真的异常。

3.3 滑动窗口的实现

滑动窗口的配置主要是三个参数:窗口时长、统计间隔、连续触发次数。比如我们要设一个5分钟的滑动窗口,每1分钟统计一次,连续3次异常才告警,规则可以写成:

# 滑动窗口配置:窗口时长5分钟,每1分钟统计一次,连续3次触发告警
window: 5m
interval: 1m
trigger_count: 3

这里的逻辑是:每1分钟的时候,去看过去5分钟内的慢请求占比(慢请求就是响应时间超过动态阈值的请求),如果这1分钟统计的占比超过10%,就算一次触发;连续3次这样的触发,才会真正告警。

3.4 完整的告警规则配置

把上面的两个规则结合起来,再加上告警的基本信息(比如告警的对象、告警的内容),完整的配置文件(比如叫alarm-rules.yaml)如下:

rules:
  - name: dynamic-slow-query-alert  # 告警规则的名字,方便识别
    description: 基于动态阈值和滑动窗口的慢查询告警  # 告警规则的描述
    # 告警的触发条件:接口是/api/user/info,慢请求占比超过10%
    trigger: "service_traffic[service_name = 'user-service', endpoint_name = '/api/user/info'] / total_traffic > 10%"
    # 动态阈值:过去1小时的平均响应时间 + 2倍标准差
    threshold: "avg(response_time, 1h) + 2 * stddev(response_time, 1h)"
    # 滑动窗口配置:窗口时长5分钟,每1分钟统计一次,连续3次触发告警
    window: "5m"
    interval: "1m"
    trigger_count: 3
    # 告警的目标:可以是邮件、企业微信、Slack等,这里用企业微信举例
    targets:
      - type: "wechat"
        url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的企业微信机器人key"

这个配置的意思是:每1分钟统计一次过去5分钟内,“user-service”服务下“/api/user/info”接口的慢请求占比(慢请求指响应时间超过过去1小时平均加2倍标准差的请求),如果连续3次统计的占比都超过10%,就给企业微信发告警。

四、应用场景:哪些情况适合用这个规则?

这个规则不是万能的,但适合大部分线上服务的监控场景,具体来说:

  1. 业务波动大的接口:比如电商的商品详情接口、订单接口,早高峰和半夜的流量差很多,传统定死阈值的规则会误报,动态阈值能跟着业务调整。
  2. 对稳定性要求高的核心接口:比如支付接口、登录接口,这些接口不能有持续的慢请求,滑动窗口能排除偶然情况,确保告警的准确性。
  3. 新上线的接口:新接口的响应时间没有历史数据,传统规则没法设合理的阈值,动态阈值可以根据上线后的运行数据自动调整,不需要人工干预。

五、技术的优缺点:有没有坑?

5.1 优点

  1. 告警准确率高:动态阈值避免了定死阈值的误报,滑动窗口排除了偶然情况,只有真的持续异常才会告警。
  2. 适配业务变化:不管是早高峰、大促,还是业务调整导致的接口响应时间变化,规则都能自动适应,不需要人工修改。
  3. 减少运维负担:不用再天天调整阈值,不用再处理大量的误报告警,节省了运维和开发的时间。

5.2 缺点

  1. 需要足够的历史数据:动态阈值的计算依赖过去一段时间的运行数据,如果是新上线的接口,前1小时的数据不够,可能会导致阈值计算不准,前1小时的告警可能会有问题。
  2. 配置稍微复杂:比传统的定死阈值规则多了动态阈值和滑动窗口的配置,需要理解每个参数的意思,对新手来说可能有点难。
  3. 统计压力稍微大一点:动态阈值需要实时计算平均、标准差等统计值,滑动窗口需要实时统计窗口内的异常情况,对SkyWalking OAP的性能有一点影响,但一般线上服务的OAP都能承受。

六、注意事项:怎么避免踩坑?

  1. 新接口的处理:新上线的接口可以先开一个“观察期”,比如前1小时不触发告警,等有足够的历史数据后再开告警,或者前1小时用一个临时的定死阈值,等数据足够后再切换成动态阈值。
  2. 参数的调整:2倍标准差是常用的,但如果你的接口波动特别大,比如大促的时候波动特别厉害,可以调整成3倍标准差;滑动窗口的参数也可以根据业务调整,比如对核心接口可以把连续触发次数设成2,非核心接口设成3,窗口时长也可以根据业务的波动周期调整,比如大促的时候窗口时长设成10分钟。
  3. 监控指标的选择:除了响应时间,动态阈值和滑动窗口也可以用到其他指标上,比如错误率(超过动态阈值的错误率占比)、QPS(超过动态阈值的QPS异常),比如我们可以配置一个动态错误率告警:
rules:
  - name: dynamic-error-rate-alert  # 动态错误率告警
    description: 基于动态阈值和滑动窗口的错误率告警
    trigger: "error_traffic[service_name = 'user-service', endpoint_name = '/api/user/info'] / total_traffic > 5%"
    threshold: "avg(error_rate, 1h) + 2 * stddev(error_rate, 1h)"
    window: "5m"
    interval: "1m"
    trigger_count: 3
    targets:
      - type: "wechat"
        url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的企业微信机器人key"

这个配置的意思是:连续3次统计过去5分钟内的错误率占比超过5%,且错误率超过过去1小时平均加2倍标准差,就告警。

七、总结

传统的SkyWalking告警规则不准,本质是没有考虑业务的变化和偶然情况,而动态阈值+滑动窗口的组合,正好解决了这两个问题。动态阈值让告警跟着业务走,滑动窗口排除偶然情况,两者结合起来,能大幅提高告警的准确率,减少运维和开发的负担。

在实际使用的时候,要根据自己的业务场景调整参数,比如新接口的观察期、标准差的倍数、滑动窗口的时长等,还要注意OAP的性能,确保配置的规则不会影响监控系统的正常运行。