构建监控系统时,很多人都倾向于采用某种量化指标的平均值∶延迟平均值,节点的平均CPU使用率,数据库容量的平均值等。后两个例子中存在的问题是很明显的∶CPU和数据库的利用率可能波动很大,但是同样的道理也适用于延迟。如果某个Web服务每秒处理1000个请求,平均请求延迟为100ms。那么1%的请求可能会占用5s时间。如果用户依赖几个这样的服务来渲染页面,那么某个后端请求的延迟的99%可能就会成为前端延迟的中位数。
区分平均值的"慢"和长尾值的"慢"的一个最简单办法是将请求按延迟分组计数(可以用来制作直方图)∶延迟为0~10ms之间的请求数量有多少,30~100ms之间,100~300ms 之间等。将直方图的边界定义为指数型增长(这个例子中倍数约为3)是直观展现请求分布的最好方式。
系统的不同部分应该以不同的精度进行度量,例如∶ ● 观察 1分钟内的CPU平均负载可能会错失导致长尾延迟过高的某种较长时间的CPU 峰值现象。 ● 对于一个每年停机时间小于9小时的Web 服务来说(年度可用率99.9%),每分钟检测 1次或2次的监控频率可能过于频繁。 ● 对目标可用率为 99.9%的某个服务每 1分钟或者2分钟检查一次硬盘剩余空间可能也是没必要的。
应该仔细设计度量指标的精确度。每秒收集CPU 负载信息可能会产生一些有意思的数据,但是这种高频率收集、存储、分析可能成本很高。如果我们的监控目标需要高精度数据、但是却不需要极低的延迟,可以通过一些内部采样机制外部汇总的方式降低成本。
例如∶ 1.将当前 CPU 利用率按秒记录。 2.按 5% 粒度分组,将对应的 CPU 利用率计数 +1。 3.将这些值每分钟汇总一次。
这种方式使我们可以观测到短暂的CPU 热点,但是又不需要为此付出高额成本进行收集和保留高精度数据。
将之前讨论的所有需求累加起来可能会形成一个非常复杂的监控系统——以下是几个复杂度的例子∶
● 不同的延迟阈值,在不同的百分位上,基于各种各样不同的指标进行报警。 ● 检测和揭示可能的故障原因。 ● 给每种可能的原因构建对应的监控台页面。
复杂是没有止境的。就像任何其他软件系统一样,监控系统可能会变得过于复杂,以至于经常出现问题,变更非常困难,维护起来难度很大。
因此,设计监控系统时一定要追求简化。在选择需要检测什么的时候,将下列信息记在心里∶
● 那些最能反映真实故障的规则应该越简单越好,可预测性强,非常可靠。 ●那些不常用的数据收集、汇总,以及警报配置应该定时删除(某些SRE团队的标准是一个季度没有用到一次即将其删除)。 ●收集到的信息,但是没有 给任何监控台,或者被任何警报规则使用的应该定时删除。
在 Google的经验里,指标的收集和汇总,加上警报系统与监控台系统,作为一个相对独立的系统运行是比较好的。(事实上,Google的监控系统是作为多个二进制文件运行的,但是通常人们把它们当成一个整体来学习。)将监控系统与其他的复杂系统操作结合起来(例如系统性能统计,单独进程的调试,异常或者崩溃的跟踪,负载测试,日志收集和分析,流量检测等)会导致监控系统过于复杂,容易出现问题。和其他软件工程的理念一样,保持系统相对独立,清晰简单,松耦合的接口是更好的策略(例如,利用Web API来收集性能数据,采用一种可以持续很久不变的简单数据格式)。
|