第三方数据延迟不能出款 云原生监控事实标准—Prometheus基本原理与开发指南
监控系统概述
1.1.监控的作用 ★
为了构建稳定性保障体系,核心就是在干一件事:减少故障。
减少故障有两个层面的意思,一个是做好常态预防,不让故障发生;另一个是如果故障发生,要能尽快止损,减少故障时长,减小故障影响范围。监控的典型作用就是帮助我们发现及定位故障。
监控的其他作用:日常巡检、性能调优的数据佐证、提前发现一些不合理的配置。
之所以能做到这些,是因为所有优秀的软件,都内置了监控数据的暴露方法,让用户可以对其进行观测,了解其健康状况:比如各类开源组件,有的是直接暴露了 接口,有的是暴露了 HTTP JSON 接口,有的是通过 JMX 暴露监控数据,有的则需要连上去执行命令。另外,所有软件都可以使用日志的方式来暴露健康状况。
因此,可被监控和观测,也是我们开发软件时必须考虑的一环。
1.2.监控架构分类 ★
1.1.1. (指标)
定义:可进行聚合计算的原子型数据,通常通过多个标签值来确定指标唯一性。
特点:指标数据仅记录时间戳和对应的指标数值,通常存储在时间序列数据库中(TSDB),存储成本低,可用于渲染趋势图或柱状图,可灵活配置告警规则,对故障进行快速发现和响应;但是不适合用于定位故障原因。
实现方案:、Open-、
1.1.2. (日志)
定义:离散事件,是系统运行时发生的一个个事件的记录。
特点:日志数据可以记录详细的信息(请求响应参数、自定义文字描述、异常信息、时间戳等),一般用于排查具体问题;日志通常存储在文件中,数据非结构化,存储成本高,不适合作为监控数据的来源。
实现方案:ELK、Loki
1.1.3. (链路)
定义:基于特定请求作用域下的所有调用信息。
特点:一般需要依赖第三方存储,在微服务中一般有多个调用信息,如从网关开始,A服务调用B服务,调用数据库、缓存等。在链路系统中,需要清楚展现某条调用链中从主调方到被调方内部所有的调用信息。不仅有利于梳理接口及服务间调用的关系,还有助于排查慢请求或故障产生的原因。
实现方案:、、
1.3. 指标监控发展史
1.3.1.
企业级的开源解决方案,擅长设备、网络、中间件的监控。
优点:
l 平台兼容性好,可运行在 、Linux、、AIX、OS X等平台上;
l 架构简单,易于维护、备份。
缺点:
l 使用数据库存储,无法水平扩展,容量有限;
l 面向资产管理的逻辑,使得监控指标的数据结构固化,没有灵活的标签设计,无法适应云原生架构下动态多变的环境。
1.3.2. Open-
Open- 最初来自小米,14 年开源,当时小米有 3 套 ,1 套业务性能监控系统 。Open- 的初衷是想做一套大一统的方案,来解决这个乱局。
优点:
l 比容量大得多,不仅可以处理设备、中间件层面监控,还可以处理应用层面监控;
l Go语言开发,易于二次开发。
缺点:
l 组件拆分比较散,部署相对比较麻烦;
l 生态不够庞大,开源软件的治理架构不够优秀。
1.3.3.
的设计思路来自,就像 是为 Borg 而生的,而 就是为 而生的。提供了多种服务发现机制,大幅简化了 的监控。
.0版本开始,重新设计了时序库,性能和可靠性都大幅提升。
优点:
l 对 支持很好, 是云原生架构下监控的标配;
l 生态庞大,有各种各样的 ,支持各种各样的时序库作为后端的备用存储,也有很好的支持多种不同语言的 SDK,供业务代码嵌入埋点。
缺点:
l 设置数据采集和告警策略需要修改配置文件,协同起来比较麻烦。
l 参差不齐,通常是一个监控目标一个 ,管理成本较高。
1.4. 指标监控典型架构 ★
1.4.1. 采集器 ★
有两种典型的部署方式,一种是跟随监控对象部署,比如所有的机器上都部署一个采集器,采集机器的 CPU、内存、硬盘、IO、网络相关的指标;另一种是远程探针式,比如选取一个中心机器做探针,同时探测很多个机器的 PING 连通性,或者连到很多 MySQL 实例上去,执行命令采集数据。
:
公司的产品,主要配合 使用。 也可以把监控数据推给 存储;
是指标领域的 All-In-One 采集器,支持各种采集插件,只需要使用这一个采集器,就能解决绝大部分采集需求;
采集的很多数据都是字符串类型,但如果把这类数据推给 生态的时序库,比如 、M3DB、 等,它就会报错。
是专门用于 生态的采集器,但是比较零散,每个采集目标都有对应的 组件,比如 MySQL 有 ,Redis 有 ,JVM 有 。
的核心逻辑,就是去这些监控对象里采集数据,然后暴露为 协议的监控数据。比如 ,就是连上 MySQL,执行一些类似于 show 、show 、show slave 这样的命令,拿到输出,再转换为 协议的数据;
很多中间件都内置支持了 ,直接通过自身的 / 接口暴露监控数据,不用再单独伴生 ;比如 中的各类组件,比如 etcd,还有新版本的 、 ;
不管是还是支持协议的各类组件,都是提供 HTTP 接口(通常是 / )来暴露监控数据,让监控系统来拉,这叫做 PULL 模型。
-Agent
公司推出的一款 All-In-One 采集器,不但可以采集指标数据,也可以采集日志数据和链路数据。
如何快速集成各类采集能力的呢?-Agent 写了个框架,方便导入各类 ,把各个 当做 Lib 使用,常见的 Node-、Kafka-、-、- 等,都已经完成了集成。对于默认没有集成进去的 ,-Agent 也支持用 PULL 的方式去抓取其他 的数据,然后再通过 Write 的方式,将采集到的数据转发给服务端。
很多时候,一个采集器可能搞不定所有业务需求,使用一款主力采集器,辅以多款其他采集器是大多数公司的选择。
1.4.2. 时序库
TSDB
本地存储经历过多个迭代:V1.0(2012年)、V2.0(2015年)、V3.0(2017年)。最初借用第三方数据库,1.0版本性能不高,每秒只能存储5W个样本;2.0版本借鉴了 压缩算法,将每个时序数据以单个文件方式保存,将性能提升到每秒存储8W个样本;2017年开始引入时序数据库的3.0版本,并成立了 TSDB开源项目,该版本在单机上提高到每秒存储百万个样本。
3.0版本保留了2.0版本高压缩比的分块保存方式,并将多个分块保存到一个文件中,通过创建一个索引文件避免产生大量的小文件;同时为了防止数据丢失,引入了WAL机制。
针对时序存储场景专门设计了存储引擎、数据结构、存取接口,国内使用范围比较广泛,可以和 、 等良好整合,生态是非常完备的。
不过 开源版本是单机的,没有开源集群版本。
M3DB
M3DB 是 Uber 的时序数据库,M3 在 Uber 抗住了 66 亿监控指标,这个量非常庞大。其主要包括4个组件:M3DB、M3 、M3 Query、M3 ,我们当前产品中的远程存储就是通过M3DB实现的。
1.4.3. 告警引擎 ★
用户会配置数百甚至数千条告警规则,一些超大型的公司可能要配置数万条告警规则。每个规则里含有数据过滤条件、阈值、执行频率等,有一些配置丰富的监控系统,还支持配置规则生效时段、持续时长、留观时长等。
告警引擎通常有两种架构,一种是数据触发式,一种是周期轮询式。
数据触发式,是指服务端接收到监控数据之后,除了存储到时序库,还会转发一份数据给告警引擎,告警引擎每收到一条监控数据,就要判断是否关联了告警规则,做告警判断。因为监控数据量比较大,告警规则的量也可能比较大,所以告警引擎是会做分片部署的,这样的架构,即时性很好,但是想要做指标关联计算就很麻烦,因为不同的指标哈希后可能会落到不同的告警引擎实例。
周期轮询式,通常是一个规则一个协程,按照用户配置的执行频率,周期性查询判断即可,做指标关联计算就会很容易。像 、、 等,都是这样的架构。
生成事件之后,通常是交给一个单独的模块来做告警发送,这个模块负责事件聚合、收敛,根据不同的条件发送给不同的接收者和不同的通知媒介。
1.4.4. 数据展示
监控数据的可视化也是一个非常通用且重要的需求,业界做得最成功的是,采用插件式架构,可以支持不同类型的数据源,图表非常丰富,基本是开源领域的事实标准。
2. 入门
2.1.主要特点
l 多维度数据模型的灵活查询;
l 定义了开放指标数据的标准,自定义探针(等);
l Go语言编写,拥抱云原生;
l 数据采集方式以pull为主、push为辅;
l 二进制文件直接启动、也支持容器镜像化部署;
l 支持多种语言客户端;
l 支持本地和第三方远程存储、高效的存储;
l 可扩展,功能分区+联邦集群;
l 结合可以做到出色的可视化功能;
l 精确告警:基于可以进行告警设置、预测等;另外还提供了分组、抑制、静默等功能防止告警风暴;
l 支持动态发现机制:;
2.2. 局限性
l 主要针对性能和可用性监控,不适用日志、事件、调用链等监控;
l 关注近期发生的事,而不是跟踪数周或数月的数据,监控数据默认保留15天;
l 本地存储有限,存储大量历史数据需要对接第三方远程存储;
l 采用联邦集群方式时,没有提供统一的全局视图。
2.3. 架构剖析 ★
u Job/
监控探针,共收录有上千种,用于对第三方系统进行监控,方式是获取第三方系统的监控数据然后按照的格式暴露出来;没有探针的第三方系统也可以自己定制开发。
不过种类繁多会导致维护压力大,也可以考虑用 Data公司开源的统一进行管理。使用集成比单独使用拥有更低的内存使用率和CPU使用率。
u
是支持临时性job主动推送指标的中间网关。
使用场景:临时/短作业、批处理作业、应用程序与之间有防火墙或不在同一个网段;
不过该解决方案存在单点故障问题、必须使用的API从推送网关中删除过期指标。
u (服务发现机制)
可以使用的API获取容器信息的变化来动态更新监控对象;
u (核心监控服务)
i. (抓取)
从Job、、个组件中通过HTTP轮询的形式拉取指标数据;
ii. (存储)
本地存储:直接保存到本地磁盘,从性能上考虑,建议使用SSD且不要保存超过一个月的数据;
远程存储:适用于存储大量监控数据,支持的远程存储包括、、M3DB、等;需要配合中间层适配器进行转换;
iii. (查询)
多维度数据模型的灵活查询。
u (可视化)
实际工作中使用,也可以调用HTTP API发送请求获取数据;
u (告警引擎)
独立的告警组件,可以将多个配置成集群,支持集群内多个实例间通信;
3. 入门
3.1. 初识 ★
3.1.1. 时间序列 ★
按照一定的时间间隔产生的一个个数据点,这些数据点按照时间戳和值的生成顺序存放,得到了向量()。
每条时间序列是通过指标名称和一组标签集来命名的。
矩阵中每一个点都可以称之为一个样本(),主要有3方面构成:
指标():包括指标名称()和一组标签集名称;
时间戳():默认精确到毫秒;
样本值(Value):默认使用64位浮点类型。
3.1.2. 指标 ★
时间序列的指标可以基于设计为Key-Value存储的方式:
的可以有两种表现方式(指标名称只能由ASCII字符、数字、下划线、冒号组成,冒号用来表示用户自定义的记录规则):
分别对应的查询形式(以下两个查询语句等价):
3.2. 4大选择器
3.2.1. 匹配器
u 相等匹配器(=):对于不存在的标签可以使用Label=""的形式查询
u 不等匹配器(!=):相等匹配器的否定
u 正则表达式匹配器(=~):前面或者后面加上".*"
u 正则表达式相反匹配器(!~):正则表达式匹配器的否定
3.2.2. 瞬时向量选择器
用于返回在指定时间戳之前查询到的最新样本的瞬时向量。
编辑
3.2.3. 区间向量选择器
高级应用:
3.2.4. 偏移量修改器
编辑
瞬时偏移向量
3.3. 4大指标类型 ★
3.3.1. 计数器()★
只增不减,一般配合rate(统计时间区间内增长速率)、topk(统计top N的数据)、等函数使用;
(v range-)获取区间向量的第一个和最后一个样本并返回其增长量:
为什么函数算出来的值非33?真实计算公式:(360 - 327) / ( - ) * 120 = 37.771
irate(v range-)是针对长尾效应专门提供的用于计算区间向量的增长速率的函数,反应的是瞬时增长率,敏感度更高。长期趋势分析或告警中更推荐rate函数。
rate(v range-) 求取的是每秒变化率,也有数据外推的逻辑, 的结果除以 range- 的时间段的大小,就是 rate 的值。
rate(s{id="PS Eden Space"}[1m]) 与 (s{id="PS Eden Space"}[1m])/60.0 是等价的
3.3.2. 仪表盘(Gauge) ★
表示样本数据可任意增减的指标;实际更多用于求和、取平均值、最大值、最小值。
可以让sum函数根据相同的标签进行求和,但是忽略掉函数覆盖的标签;如上图,可以忽略掉id,只按照堆/非堆的区别进行内存空间求和。
3.3.3. 直方图() ★
用于描述数据分布,最典型的应用场景就是监控延迟数据,计算 90 分位、99 分位的值。
有些服务访问量很高,每秒几百万次,如果要把所有请求的延迟数据全部拿到,排序之后再计算分位值,这个代价就太高了。使用 类型,可以用较小的代价计算一个大概值。
的类型计算原理:桶排序+假定桶内数据均匀分布。
这种做法性能有了巨大的提升,但是要同时计算成千上万个接口的分位值延迟数据,还是非常耗费资源的,甚至会造成服务端 OOM。
数据解析::9090/
3.3.4. 汇总() ★
在客户端计算分位值,然后把计算之后的结果推给服务端存储,展示的时候直接查询即可。
的计算是在客户端计算的,也就意味着不是全局(整个服务)的分位值,分位值延迟数据是进程粒度的。
负载均衡会把请求均匀地打给后端的多个实例。一个实例内部计算的分位值,理论上和全局计算的分位值差别不会很大。另外,如果某个实例有故障,比如硬盘问题,导致落在这个实例的请求延迟大增,我们在实例粒度计算的延迟数据反而更容易发现问题。
数据解析::9090/ ds
3.4. 13种聚合操作
l 和 by 用来保留不同维度的可选操作符,其余11个聚合操作都是用于瞬时向量,使用相同的分组逻辑:
l sum
l min
l max
l avg
l count
l (对value进行计数)
l (标准差)
l (标准差异)
l (样本值最小k个元素)
l topk(样本值最大k个元素)
l (分布统计)
3.4.1. 、by ★
上述两个查询是等价的;同一个聚合语句中不可同时使用by和,by的作用类似于sql语句中的分组(group by),语义是:除开XX标签,对剩下的标签进行分组。
3.4.2.
数学中称为方差,用于衡量一组数据的离散程度:数据分布得越分散,各个数据与平均数的差的平方和越大,方差就越大。
3.4.3.
标准差:用方差开算术平方根。
3.4.4. count、
count:对分组中时间序列的数目进行求和
:表示时间序列中每一个样本值(value)出现的次数,实践中一般用于统计版本号。
3.4.5.
用于计算当前样本数据值的分布情况,例如计算一组http请求次数的中位数:
3.5. 3种二元操作符
3.5.1. 算术运算符(加减乘除模幂)
3.5.2. 集合/逻辑运算符
仅用于瞬时向量之间,and(并且)、or(或者)、(排除)
内置函数扮演了not的角色;
应用场景,配置告警规则:
3.5.3. 比较运算符(== != > = 0, tf