目录
前言
任何小型系统在成长为大型的复杂系统后,工程师们都会面临一个非常现实的问题:几乎没有人能够完全描述和掌握这么复杂的系统。 以几个特定领域为例:
医学,人体内部有血液、神经元、激素、细胞,通过体温、血压、血糖、心率、CT、MRI、血液指标来诊断病因。 汽车,发动机内部有气缸、火花塞、燃烧室,通过转速、油耗、温度来推断发动机运行情况。 企业管理,每个人都有自己琐碎细微的工作,老板必须通过收入、支出、现金流、客户数等来把握企业的健康状况。 社会和经济,企业活动和居民消费往往无法观测,那么就需要通过 GDP、失业率等指标来观察一个国家的运行情况。
所有的复杂系统最后走向控制理论中的可观测性:通过一些有限的外部信号和指标,来推测和理解复杂系统内部的运行状态。
软件工程中的可观测性也是如此,在现代大型软件里,很多系统或者模块已经脱离了简单的单体模式,走向了错综复杂的分布式架构,在生产环境下,为了保证系统出错时可以快速纠错,甚至提前预知问题的发生,让系统更加透明化的运行,就需要给系统加上一套“感官装置”,让工程师能够理解、诊断、观察、预测整个系统。
三个支柱
可观测性由三个支柱组成:
- Metrics
- Logs
- Traces
Metrics 即指标,用于提供一些可以被量化的内容。 Logs 即日志,系统在运行过程中主动记录的一些关键性信息。 Traces 即链路追踪,系统中为了完成某个任务或者事务,可能需要调用 n 个接口和 n 个函数,Traces 可以把属于同一个事务的调用链完整的呈现出来。
Metrics
指标
指标就像是汽车、飞机上的仪表盘,提供了各种可以量化的数据,我们不需要在大脑中记住每一个业务逻辑的所有调用链,只需要观察指标就可以看出系统的健康度和基本状态。 比较经典的组合是 Grafana + Prometheus,Prometheus 包含了时序数据库从 node 中收集信息,Grafana 负责对数据进行可视化展示。
对于不同的观测对象,所需要提取的指标是不同的:
- 服务器:CPU、内存、磁盘 IO、网络 IO。
- 后端应用:GC,接口响应时间,可用性,错误率。
- 消息队列:消息积压量,生产/消费速率,延迟。
- 关系型数据库:连接池,慢查询数量,锁和事务
- 非关系型数据库:比如 Redis 需要看内存使用,命令吞吐量。
收集
指标可以理解为随着时间积累的一连串数据,也就是时间序列。收集连续时间下的指标数据,可以统计某个指标的增长率,增量,在一定范围内的平均值等等信息。
告警
团队可以建立指标阈值,一旦突破,就会触发警报以通知工作人员当前或即将出现的问题。
比如 CPU 突然飙高,磁盘持续超过 80% 占用,数据库连接数异常等等,这些 metrics 可以关联到 alert。
告警不能过少,会导致异常已经发生了,但是运维人员却毫不知情,告警也不能过多,过多的告警淹没了真正重要的信息。我们应该尽可能地做到,凡是告警的信息,都是需要人介入干预的事情。如果一个告警经常发生,以至于会让人说出一句:噢,看了一下,没什么问题,忽略就好,那么这个告警的设置就是糟糕的。
告警可以站在客户端和服务端的角度来看,从客户端的角度触发,用户关心的是服务爆 5xx,请求超时,页面打不开,数据错误,所以这些都是应用“生病”的症状,对于症状的监控可以让运维人员更加靠近用户。而服务端可能更加看重 CPU、内存、磁盘、数据库、网络等等,但这些问题都属于应用“生病”的根因,服务端的一些问题,可能并不会导致用户体验的变化,比如有做好冗余的集群里,有一台服务器挂了,但是用户感知不到,或者网络抖动了一下,但用户重试就能成功,如果对所有琐碎的小问题都做告警,那么 on-call 系统就会被细节淹没。
更好的做法是,站在用户的角度,用症状触发告警,并且用服务端的根因辅助诊断。
和日志类似,需要对告警的类型和重要程度进行区别:
- 紧急,比如,服务器频繁爆出 500,正在影响用户,或 4 小时内会严重影响使用,需要电话或者短信告警。
- 工单,比如磁盘 3 天后可能会满,需要建立工单。
- 每日巡检,慢请求数量,容量接近阈值,非核心任务的失败,可以通过邮件告警。
所有,建立一个好的告警体系,首先需要了解实际用户接触的业务流程,要看用户依赖什么,针对这些方面优先建立告警,比如:支付、登录、下单是否能够成功,数据是否正确,响应延迟等。 其次,在服务端针对预测性问题进行告警,比如服务端的资源:CPU、内存、磁盘、队列等。
分析和可视化
过多的数据必然需要可视化的界面来汇总和分析(比如:Grafana 和 Kibana)。在我做过的项目里,政府类的信息化项目是最喜欢监控大屏,领导喜欢看一大堆漂亮的指标图片,有种尽在掌握之中的感觉,但在最佳实践中,堆砌表格、柱状图、折线图是在增加系统的“噪音”,选取必要的指标做可视化,并且对有关联、可预测的数据做针对性的可视化处理。
以磁盘为例,它的指标就是一个百分比数字,最简单的就是一个环形图或者别的可以表示占比的控件,但在可视化中我们也许能传达更加具体有用的信息,磁盘用量的百分比是一个瞬时值,如果可以和时间关联,做成一个时间序列的折线图,那么就可以清晰地看到磁盘占比随着时间的变化,更进一步,可以通过时间序列得到近 N 天的磁盘用量百分比最高、最低点或者其他一些统计学的信息。
从有效提示的角度,运维人员可能更关心他们什么时候需要人工介入来释放磁盘空间,可以通过过往的数据,得到磁盘占用变化的速率,可以推测未来多少时间内磁盘会超过设定的阈值,有时候磁盘占比很低,但占用量升高的速度很快,就需要告警,可视化也可以展现出来用醒目的红色来表示(预计 3 小时后磁盘占用将超过 80%)。
针对不同的指标类型,需要采用不同的可视化语言:
- 随时间变化的,使用折线图
- 了解最好、最坏、最多、最少,观察每个元素的数量,使用柱状图
- 查看数值集中在哪些范围,使用直方图
- 查看离散的事件发生时间,使用时间轴
- 多个同类指标随时间变化,使用堆叠面积图
- 对于有依赖关系的指标信息,比如故障在哪条链路上传播,使用拓扑图
- 统计多个指标的相关性,使用散点图
- 系统当前各个指标的顺势状态,使用数字卡
- 二维指标找到异常点,使用热力图
Logs
结构化日志
Traces
参考
- https://www.ibm.com/think/insights/observability-pillars
- https://loggingsucks.com/
- https://plumephp.com/observability-logging-metrics-tracing
- https://opentelemetry.io/docs/what-is-opentelemetry/
- https://prometheus.ac.cn/docs/prometheus/latest/getting_started/
- https://docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q/edit?pli=1&tab=t.0#heading=h.fs3knmjt7fjy
- https://prometheus.io/docs/introduction/overview/
- https://prometheus.io/docs/alerting/latest/alertmanager/
- https://aleiwu.com/post/prometheus-bp/