实用异常检测

2015年6月18日作者 Brian Brazil

在其致监控/指标/告警公司的公开信 中,John Allspaw断言,“完美地、适时地检测异常是不可能的”。

我曾看到过才华横溢的工程师们尝试构建系统,以基于时间序列数据自动检测和诊断问题。虽然演示肯定是可以实现的,但对于最简单的实际系统之外的任何应用,数据总是显得过于嘈杂,无法使这种方法奏效。

不过,希望并非完全渺茫。有很多常见的异常,你可以通过自定义规则来检测和处理。Prometheus的查询语言为你提供了发现这些异常并避免误报的工具。

构建查询

服务中一个常见的问题是,一小部分服务器的性能不如其他服务器,例如响应延迟增加。

假设我们有一个指标instance:latency_seconds:mean5m,它表示服务每个实例的平均查询延迟,是通过记录规则Summary指标计算得出的。

一个简单的开始方法是查找延迟高于平均值两个标准差的实例

  instance:latency_seconds:mean5m
> on (job) group_left()
  (
      avg by (job)(instance:latency_seconds:mean5m)
    + on (job)
      2 * stddev by (job)(instance:latency_seconds:mean5m)
  )

你尝试这样做,发现当延迟非常紧密地聚集在一起时会出现误报。因此,你增加了一个要求,即实例延迟也必须高于平均值20%。

  (
      instance:latency_seconds:mean5m
    > on (job) group_left()
      (
          avg by (job)(instance:latency_seconds:mean5m)
        + on (job)
          2 * stddev by (job)(instance:latency_seconds:mean5m)
      )
  )
> on (job) group_left()
  1.2 * avg by (job)(instance:latency_seconds:mean5m)

最后,你发现误报往往发生在流量较低的时候。你增加了一个要求,即每个实例要有足够高的流量,每秒要有1个查询。你为此创建了一个告警定义。

groups:
- name: Practical Anomaly Detection
  rules:
  - alert: InstanceLatencyOutlier
    expr: >
      (
            (
                instance:latency_seconds:mean5m
              > on (job) group_left()
                (
                    avg by (job)(instance:latency_seconds:mean5m)
                  + on (job)
                    2 * stddev by (job)(instance:latency_seconds:mean5m)
                )
            )
          > on (job) group_left()
            1.2 * avg by (job)(instance:latency_seconds:mean5m)
        and on (job)
            avg by (job)(instance:latency_seconds_count:rate5m)
          >
            1
      )
    for: 30m

自动操作

上述告警可以输入到Alertmanager,然后从那里发送到你的聊天、票务或呼叫系统。一段时间后,你可能会发现告警的常见原因是某个问题没有得到妥善修复,但可以通过自动操作(如重启、重引导或更换机器)来解决。

与其让人类处理这项重复性任务,不如让Alertmanager将告警发送到一个执行操作的Web服务,该服务将具有适当的限流和安全功能。

通用的Webhook会将告警通知发送到你选择的HTTP端点。一个简单的使用它的Alertmanager配置可能如下所示:

# A simple notification configuration which only sends alert notifications to
# an external webhook.
receivers:
- name: restart_webhook
  webhook_configs:
    url: "http://example.org/my/hook"

route:
  receiver: restart_webhook

总结

Prometheus查询语言允许对你的监控数据进行丰富的处理。这使得你可以创建信噪比高的告警,而Alertmanager的通用Webhook支持可以触发自动修复。所有这些结合起来,使得值班工程师能够专注于他们能够产生最大影响的问题。

在为你的服务定义告警时,请参阅我们的告警最佳实践