Prometheus 精要(一)

关于可观测性

记录所有事件的所有上下文,对调试或者了解当前系统的状况,于技术、于业务而言,都是非常有益的,但是需要处理和存储海量的数据,这是不现实的。

大概有四种方式来减少数据量,让处理和存储这些数据变得可实现:

  • Profiling(性能剖析)

    特点:只采样短期内发生的事件,包含完整上下文

    例子:tcpdump

  • Tracing(追踪)

    特点:按比例采样所有事件的一部分(N%),关注调用链

    例子:jaeger

  • Logging(日志)

    特点:只记录特定事件,上下文丰富,大致分为:

    • 事务日志(例如涉及钱,不能丢失)
    • 请求日志(尽量不丢失,丢失了问题也不大)
    • 应用日志(例如启动消息、后台任务,主要是给人阅读,不会有很多)
    • 调试日志(量多,只应用在调试情景,可以随意丢失)

    各种日志的处理方式不能一概而论

  • Metrics(监控指标)

    特点:关注计数,上下文几乎没有

指标类型

Counter

累计值,只增不减。通常用来记录事件累计发生的次数,用于表现事件在时间轴上发生(次数):

例:rate(user_logins_total[1m])

Gauge

快照值。通常用来直接表现状态在时间轴上的变化:

例如:temperature

Summary

对应两个累计值,只增不减。一个记录事件累计发生的次数,一个记录事件属性的累计和,主要用于表现事件在时间轴上发生(与否),以及事件发生时的属性均值:

例如:rate(request_latency_seconds_sum)/rate(request_latency_seconds_count)

如果使用了 quantile,还会有若干个 Gauge 值对应事件属性百分位值的快照:

50%的请求延迟小于这个值:request_latency_seconds{le="0.5"}

75%的请求延迟小于这个值:request_latency_seconds{le="0.75"}

95%的请求延迟小于这个值:request_latency_seconds{le="0.9"}

注意:百分位值在客户端计算,需要消耗客户端资源。

Histogram

对应 2 + N 个累计值,只增不减。一个记录事件累计发生的次数,一个记录事件属性的累计和,其余N个记录事件在N个属性值区间上累计发生的次数:

前2个累计值的使用和 Summary 类似。

剩余N个累计值:

请求延迟值(秒)命中 [0, 0.1] 区间的累计次数:

request_latency_seconds_bucket{quantile="0.1"}

请求延迟值(秒)命中 [0, 0.5] 区间的累计次数:

request_latency_seconds_bucket{quantile="0.5"}

请求延迟值(秒)命中 [0, +Inf] 区间的累计次数 = 请求累计次数:

request_latency_seconds_bucket{quantile="+Inf"}

90%的请求延迟小于这个值(百分位值):

​ histogram_quantile(0.9, rate(request_latency_seconds_bucket[1m]))

注意:计算发生在服务端,计算结果的精度和 bucket 区间个数、每个区间的大小有关。

指标命名

  • snake case
  • 使用(无前缀)基本单位的复数作后缀,例如seconds、bytes,而不是 milliseconds、kilobytes
  • counter 再带上 total 后缀

监测的对象

服务

  • 在线服务

    监测要点:request rate, latency, error rate

  • 离线服务

    监测要点:queued work, in-progress work, work process speed, error

    可以类比为水池,需要关注水位、水位变化速度(水流入速度 - 水流出速度)

  • 批处理作业

    通常是定时作业,并非24小时运行

    监测要点:和离线服务类似,但是需要 push gateway 辅助收集指标

关注报错以及打日志的地方

何时使用标签

指标使用了某标签K=V以后,如果无视标签K进行聚合,得到的结果还有意义,说明可以使用这个标签。

容量规划

可以简单地认为 prometheus 最多能处理 1000 万个时间序列

再预设最多有 1000 个被监控的实例,每个实例平均能占用 10000 个时间序列

1 个 Gauge/Counter 占用的时间序列数 = 1 x (标签1的的值个数) x (标签2的的值个数)x(标签3的的值个数)x ... x (标签N的的值个数)

注意:要排除 instance 标签,已经被当成 1000 个值计算过了

1 个 Summary 占用的时间序列数 = (同 Gauge/Counter) x (2 + quantile 数)

1 个 Histogram 占用的时间序列数 = (同 Gauge/Counter) x (2 + bucket 区间数)

大部分指标占用的时间序列应该少于10个

少部分指标占用的时间序允许在100个左右

如果把某个标签的值展开,变成多个指标(标签值移入到指标名),例如 http_requests_total => http_get_requests_total, http_post_requests_total, http_put_requests_total ... 占用的时间序总数并没有发生变化,还加大了聚合的难度

上一篇:命令行搞一切之如何使用命令行为 redis 做健康检测


下一篇:【Coel.学习笔记】卢卡斯定理(Lucas Theorem)