DevOps系列:监控

系列目录

《DevOps系列:开篇》

《DevOps系列:概述》

《DevOps系列:CMDB》

《DevOps系列:CI/CD》

《DevOps系列:监控》

《DevOps系列:SRE》


为什么需要监控系统?

两个场景

场景一

技术部门上线了一个新项目,系统宕机了,客户在访问时发现无法访问,客户 A 不知道如何处理,放弃了访问,客户 B 知道客服系统,告知了运营人员,运营人员自己访问后也发现无法访问,于是通知了测试人员,再由测试人员通知线上项目的负责人,由负责人来进行故障恢复。 整个流程中,能处理故障的人成了最后知道故障的人。

场景二

用户反馈访问某个系统很慢,通知技术人员排查问题,由于系统涉及的组件很多,技术人员没办法立即知道问题出在哪里,于是技术人员只能通过自己把整个数据流走完的方式来排查问题: 1、由入口开始排查问题,先确认网络是否丢包,延时是否过高,发现无异常。 2、于是排查服务所在机器的负载情况,以及服务相关日志 (未必有记录),也无异常。 3、排查代码发现有做 sql 查询,于是根据 sql 手动到数据库执行,发现 sql 执行很慢。 4、于是排查数据库所在机器的负载情况,发现 cpu 一直处在 100% 状态,是数据库进程造成的。 5、通过查询相关执行 sql 发现有某个 sql 在执行复杂查询导致了 cpu 使用率一直很高,从而影响了其他 sql 查询。

极端情况下,技术人员可能需要把所有相关组件都排查一遍,才能发现问题出在哪里。


场景解决方案

开头提到的两个场景应该是大部分技术人员都会碰到的问题,场景一是故障出现到故障处理的耗时问题,场景二是故障处理到故障恢复的耗时问题。

场景一的解决方式,可以由一个脚本或者一个系统,定时收集客户访问的 url 的返回状态码,如果出现错误的状态码达到一定次数,就发送邮件或者短信给到对应的负载人。

场景二的解决方式,可以由一个系统,定时收集所有组件的相关信息,然后通过聚合和数据展示,来提供一个全局的问题查看功能。

解决上面两种场景的系统就是监控系统。


为什么要监控

监控一个系统有多个原因,一般包含如下几项

  1. 分析趋势

    数据库多大,增长速度如何?日活用户的增长速度?

  2. 数据对比

    增加了 redis 缓存后,访问速度较没增加前如何?这周和上周的访问速度有什么差异?

  3. 告警

    有东西故障了,或者即将故障,需要有人处理它。

  4. 构建仪表盘

    仪表盘应该可以回答有关服务的一些基本问题,通常会包含常见的指标

  5. 临时性回溯分析

    请求延迟刚刚大幅增加,有没有其他的现象同时发生?


建立监控系统

监控系统基本组件

一个监控系统一般包含下面几个组件:

  1. Agent/collector

    Agent/collector用于定时收集各种需要的指标信息,可以是脚本、程序、埋点。

  2. Server

    Server用于接收采集回来的指标信息,进行聚合、存储,供后续查询使用。

  3. Dashboard

    Dashboard用于展示历史指标信息

  4. Alert

    Alert用于计算告警规则,发送告警的操作


监控系统的工作流程

一个监控系统的工作流程一般如下:

  1. 数据采集

    安装客户端,可以是脚本、程序、埋点, 定时采集各种需要的数据。

  2. 数据接收、存储

    1. Push方式

      监控系统提供接口供客户端定时上报数据

    2. Pull方式

      客户端提供接口供监控系统定时拉取数据

  3. 数据处理

    1. 告警

      根据一定规则计算采集回来的指标数据,设置阈值,当达到阈值后发送告警。

    2. 展示

      提供一个仪表板,用来展示采集回来的数据

    3. 分析

      针对采集回来的数据进行定制化的数据分析


Metric

配置监控时,我们首要面对的是监控数据如何采集的问题。一般我们可以把监控指标分为两类:业务指标和资源指标。

业务指标

业务指标通过衡量有用的输出来指示系统的运行状况。一般包括以下几个

  1. 吞吐量

  2. 成功率

  3. 错误

  4. 性能(延迟)

一个Web server的业务指标例子

Subtype Description Value
throughput requests per second 312
success 上个周期响应状态码为2xx的百分比 99.1
error 上个周期响应状态码为5xx的百分比 0.1
performance 采集周期内的平均响应时间 0.4

资源指标

资源指标一般包括以下几个:

  1. 利用率

  2. 饱和度

  3. 错误

  4. 可用性

一些通用资源的指标例子

Resource Utilization Saturation Errors Availability
Disk IO % time that device was busy wait queue length # device errors % time writable
Memory % of total memory capacity in use swap usage N/A (not usually observable) N/A
Microservice average % time each request-servicing thread was busy # enqueued requests # internal errors such as caught exceptions % time service is reachable
Database average % time each connection was busy # enqueued queries # internal errors, e.g. replication errors % time database is reachable

Four Golden Signals

Four Golden Signals 是 Google 针对大量分布式监控的经验总结,4 个黄金指标可以在服务级别帮助衡量终端用户体验、服务中断、业务影响等层面的问题。主要关注与以下四种类型的指标:

  1. 延迟:服务请求所需时间。

    记录用户所有请求所需的时间,重点是要区分成功请求的延迟时间和失败请求的延迟时间

  2. 流量:监控当前系统的流量,用于衡量服务的容量需求。

    流量对于不同类型的系统而言可能代表不同的含义。例如,在 HTTP REST API 中, 流量通常是每秒 HTTP 请求数;

  3. 错误:监控当前系统所有发生的错误请求,衡量当前系统错误发生的速率。

    对于失败而言有些是显式的 (比如, HTTP 500 错误),而有些是隐式 (比如,HTTP 响应 200,但实际业务流程依然是失败的)。

    对于一些显式的错误如 HTTP 500 可以通过在负载均衡器 (如 Nginx) 上进行捕获,而对于一些系统内部的异常,则可能需要直接从服务中添加钩子统计并进行获取。

  4. 饱和度:衡量当前服务的饱和度。

    主要强调最能影响服务状态的受限制的资源。 例如,如果系统主要受内存影响,那就主要关注系统的内存状态,如果系统主要受限与磁盘 I/O,那就主要观测磁盘 I/O 的状态。因为通常情况下,当这些资源达到饱和后,服务的性能会明显下降。同时还可以利用饱和度对系统做出预测,比如,“磁盘是否可能在 4 个小时候就满了”。


Alert

报警可以让一个系统发生故障或即将发生故障时主动通知相应的人员,一个紧急报警的处理会占用对应人员的宝贵时间,如果无效信息过多,分析和修复问题课鞥呢会变慢,故障时间也会相应的延长,因此一个高效的报警系统应该能提供足够的信息,并且误报率非常低。

在管理大规模集群的情况下,究竟有多少报警量才是合理的呢?

Google SRE每周只有十条报警,如果超过十条,说明没有把无效报警过滤掉(Google SRE仅负责SLA要求为99.99%的服务)。

那么怎么减少报警量呢? 这就需要对报警进行优化了。


报警优化

1. 报警值班和报警升级

基于值班表,每天安排两人进行值班处理报警,将值班压力从全团队压缩在两人范围内,从而让团队能够有足够的时间和人力进行优化工作。

同时,为了避免两个值班人员都没有响应报警,可以使用报警升级功能,如果一个报警在5min内值班人员均未响应,或者15min内未处理完毕,或者有严重故障发生,都可以将报警进行升级,通告团队其他成员协助处理。

2. 建立报警等级

Google SRE的实践则是将监控系统的输出分为三类,报警、工单和记录。

SRE的要求是所有的故障级别的报警,都必须是接到报警,有明确的非机械重复的事情要做,且必须马上就得做,才能叫做故障级别的报警。其他要么是工单,要么是记录。

3. 故障自愈

重启作为单机预案,在很多业务线,可以解决至少50%的报警。没有响应,重启试试,请求异常,重启试试,资源占用异常,重启试试,各种问题,重启都屡试不爽。

换言之,针对简单场景具有明确处置方案的报警,自动化是一个比较好的解决方案,能够将人力从大量重复的工作中解放出来。

自动化处理报警的过程中,需要注意以下问题:

  1. 自动化处理比例不能超过服务的冗余度(默认串行处理最为稳妥);

  2. 不能对同一个问题在短时间内重复多次地自动化处理(不断重启某个机器上的特定进程);

  3. 在特定情况下可以在全局范围内快速终止自动化处理机制;

  4. 尽量避免高危操作(如删除操作、重启服务器等操作);

  5. 每次执行操作都需要确保上一个操作的结果和效果收集分析完毕(如果一个服务重启需要10min)。

4. 持续优化TOP3的报警

2/8定律,80%的报警可能来自20%的指标,对报警数过多的报警进行持续优化,可以减少大量的报警。

5. 基于时间段分而治之

从冗余度角度来分析,如果在流量峰值有20%的冗余度,那么在流量低谷,冗余度至少为50%。

基于冗余度的变换,相应的监控策略的阈值,随机也应该发生一系列的变化。

举例来说,在高峰期,可能一个服务故障20%的实例,就必须介入处理的话,那么在低谷期,可能故障50%的实例,也不需要立即处理,依赖于报警自动化处理功能,逐步修复即可。

6. 报警周期优化,避免瞬报

在监控趋势图中,会看到偶发的一些毛刺或者抖动,这些毛刺和抖动,就是造成瞬报的主要原因。

这些毛刺和抖动,至多定义为异常,而非服务故障,因此应该以非紧急的通知方式进行。

7. 提前预警,防患于未然

对于很多有趋势规律的场景,可以通过提前预警的方式,降低问题的紧迫程度和严重性。

8. 日常巡检

提前预警面向的是有规律的场景,而日常巡检,还可以发现那些没有规律的隐患。

9. 比例为主,绝对值为辅

线上机器的规格不同,如果从绝对值角度进行监控,则无法适配所有的机器规格,势必会产生大量无意义的报警。

10. Code Review

前人埋坑,后人挖坑。在解决存量问题的情况下,不对增量问题进行控制,那报警优化,势必会进入螺旋式缓慢上升的过程,这对于报警优化这类项目来说,无疑是致命的。

通过对新增监控的Code Review,可以让团队成员快速达成一致认知,从而避免监控配置出现千人千面的情况出现。

11. 沉淀标准和最佳实践

仅仅做Code Review还远远不够,一堆人开会,面对一行监控配置,大眼瞪小眼,对不对,为什么不对,怎么做更好?大家没有一个标准,进而会浪费很多时间来进行不断的讨论。

这时候,如果有一个标准,告诉大家什么是好,那么就有了评价标准,很多事情就比较容易做了。

标准本身也是需要迭代和进步的,因此大家并不需要担心说我的标准不够完美。

基于标准,再给出一些最佳的监控时间,那执行起来,就更加容易了。

12. 彻底解决问题不等于自动处理问题

自动化处理问题不等于解决问题,掩耳盗铃也不等于解决问题,什么叫做解决问题,只有是找到问题的根本原因,并消灭之,才能确保彻底解决问题,轻易不会再次发生。


参考

Google SRE 运维解密

datadog monitoring 101

摆脱无效报警?十年运维监控报警优化经验总结