# 假如今天7号
# 6号到7号的一天访问量
sum(increase(credit_insight_spl_id_all_pv{}[1d] )) by (url)
# 5号到6号的一天访问量 offset 1d
sum(increase(credit_insight_spl_id_all_pv{}[1d] offset 1d)) by (url)
# 4号到5号的一天访问量
sum(increase(credit_insight_spl_id_all_pv{}[1d] offset 2d)) by (url)
而 Prometheus 已经内置了时间段查询功能,并对此优化处理。
可通过 /api/v1/query_range
接口进行查询,获的 grpah:
Prometheus 查询瓶颈
数据存储:
指标数据有 “Writes are vertical,reads are horizontal” 的(垂直写,水平读)模式:
“Writes are vertical,reads are horizontal” 的意思是 tsdb 通常按固定的时间间隔收集指标并写入,会 “垂直” 地写入最近所有时间序列的数据,而读取操作往往面向一定时间范围的一个或多个时间序列,“横向” 地跨越时间进行查询
每个指标(metric)根据指标数量不同,有 labelA * labelB * labelC * ... 个时序图
每个时序图(time series)的一个点时序是 [timestamp, value], 例如 [1605607257, 233]。[时间戳-值] 可以确定图上的一个点,一个时间区间内的所有点连成一个时序曲线图。
因为 Prometheus 每隔 15s 采集一次数据,所以 时序点的时间间距是 15s,即1分钟有60/15=4个时序点,1小时就有 4 * 60 = 240 个时序点。
而 Prometheus 的默认查询 sample 上限是 5000w
所以,如果指标的时序图数量过大,允许查询的时间区间相对就会较小了。
一个图表查询时序数量的影响因素有 3 个,分别是:
查询条件的时序数量(n)
查询的时间区间(time)
图表曲线每个时序点之间的间隔(step)
以 credit_insight_spl_id_all_pv
指标为例,该指标总共大约有 n = 163698 种时序,
假如 step = 15s,如果搜索该指标过去 time = 60m 的全部时序图,那么,需要搜索的例子要
163698 * 60 * (60/15) = 39287520
,将近 4kw,是可以搜出来的。
但如果搜的是过去 90m 的数据,163698 * 90 * 4 = 58931280
,超过了 5000w,你就发现数据请求异常:
Error executing query: query processing would load too many samples into memory in query execution
所以,目测可得一个图的查询时序点数量公式是:total = n * time / step, time 和 step 的时间单位必须一致,total 必须不超过 5000w。
反推一下得出,time < 5000w / n * step 。要扩大搜索时间范围,增大 step ,或者降低 n 即可做到。
step 不变, 降低 n 【指定label值可减少搜索条件的结果数】 : credit_insight_spl_id_all_pv{systemType="Android", systemVersion="10"}
,n = 18955
增大 step 到 30s, n 不变:
当然,一般情况下,我们的 n 值只有几百,而 step 基本是大于 60s 的,所以一般情况下都能查询 2 个多月以上的数据图。
可视化平台: Grafana
grafana 是一个开源的,高度可配置的数据图表分析,监控,告警的平台,也是一款前端可视化的产品。
自定义图表
grafana 内置提供多种图表模板,具体是以下类型:
Prometheus 作为数据源的情况下,一般用的 graph 类型画时序图比较多。
对于一些基础的数据大盘监控,这些图表类型已经足够满足我们的需求。
但对于复杂的需求,这些类型无法满足我们的需要时,我们安装 pannel 插件,来更新可用的图表类型,也可以根据官方文档 build a panel plugin 开发自己的前端图表 panel。
在时序图表配置场景下,我们需要核心关注配置的有:
promQL: 查询语句
Legend: 格式化图例文本
step/interval: 采集点间隔,每隔一段时间,采集一次数据。
一条曲线的数据点数量 = 图表时长 / 采样间隔。例如查看最近24小时的数据,采样 间隔5min,数据点数量=24*60/5=288。
采集间隔时间越短,采样率越大,图表数据量越大,曲线越平滑。 采集间隔默认自动计算生成,也可以自定义配置。
metric time range: 每个点的数据统计时间区间时长。
以QPS为例,图表上每个时间点的数据的意义是:在这时间点上,过去n秒间的访问量。
从上图可以看到,
如果采样间隔 > 统计区间时长: 数据采样率 < 100%。未能采集到的数据丢弃,不会再图表上展示。采样率过小可能会错误异常的数据指标。。
如果采样间隔 == 统计区间时长,采样率100%。
如果采样间隔 < 统计区间时长,数据被重复统计,意义不大。
自定义变量
为了实现一些常用的筛选过滤场景,grafana 提供了变量功能
变量配置:变量配置有多种方式(Type),可以自定义选项,也可以根据prometheus 指标的 label 动态拉取。
变量使用:变量通过 $xxx
形式去引用。
除了 Prometheus 本身可以配置告警表达式之外:
grafana 也可以配置告警:
Prometheus 通常用于后端应用的指标数据实时上报,主要用于异常告警,问题排查,所以数据存在时效性,我们不会关注几个月前的一个已经被排查并 fixed 的指标异常波动告警。
但是,要是我们将 Prometheus 用于业务指标监控,那么我们可能会关注更久远的数据。
例如我们可能想要看过去一个季度的环比同比增长,用 Prometheus 作为数据源就不合适,因为 Prometheus 是时序数据库,更多关注实时数据,数据量大,当前数据保存的时效设定只有 3 个月。
那么这个时候可能我们要维护一个长期的统计数据,可能就需要存储在 mysql 或者其他存储方式。
grafana 不是 Prometheus 的专属产品,还支持多种数据源,包括但不限于:
常见数据库
MySql
SQL Server
PostgreSQL
Oracle
日志、文档数据库
Elasticsearch
时序数据库
Prometheus
graphite
openTSDB
InfluxDB
Jaeger
Zipkin
如果没有自己需要的数据源配置,还可以安装 REST API Datasource Plugin, 通过 http 接口查询作为数据源
了解 grafana 的高度可配置性设计后,有值得思考的几点:
关注其设计思想,如果要自己实现一个类似的可视化的 web app,自己会怎么设计?
自己要做一个高度可配置化的功能,又应该怎么设计?
深入到业务,例如我们常用的 admin 管理 系统,一些常用的业务功能是否可以高度可配置化?业务强关联的如何做到配置与业务的有机结合?
等等这些,其实都是值得我们去思考的。
此外,Prometheus 和 grafana 都有些进阶的玩法,大家有兴趣也可以去探索下。
Prometheus 的数据存储实现【理论篇】
prometheus tsdb 的存储与索引
query processing would load too many samples into memory in query execution