Metrics

齐文栋
2023-12-01

区别 count 和 gauge 的方法: 看此值是否可增可减。若可增可减,则为 gauge。反之若只能增,那就是 count。

1. StatsD

1.1. 关于 statsd timer 的几个指标

1.1.1. 指标列表

比如 450 120 553 994 334 844 675 496 这样一系列数据

即 (120 334 450 496 553 675 844 994)。

1.1.2. count

count of the items processed

总数, 这里是 8 个

1.1.3. max/upper

The largest value

最大值, 这里是 994

1.1.4. min/lower

The smallest value

最小值, 这里是 120

1.1.5. sum

Total of items

总和, 这里是 4466

1.1.6. mean

average of the items

平均值, 这里是 558.25

1.1.7. sum_90

The sum of values up to the 90th percentile

按大小升序, 前 90% 的数据总和, 这里是 3472(4466-994)

1.1.8. upper_90

The upper value of the 90th percentile group

按大小升序, 前 90% 的数据中最大的数, 这里是 844

1.1.9. mean_90

The average of values up to the 90th percentile

按大小升序, 前 90% 的数据的平均值, 这里是 496

1.1.10. 90thPercentile

一组 n 个观测值按数值大小排列, 处于 p% 位置的值称第 p 百分位数。百分位通常用第几百分位来表示, 如第五百分位, 它表示在所有测量数据中, 测量值的累计频次达 5%

百分位数提供了有关各数据项如何在最小值与最大值之间分布的信息。对于无大量重复的数据, 第 p 百分位数将它分为两个部分。大约有 p% 的数据项的值比第 p 百分位数小; 而大约有 (100-p)% 的数据项的值比第 p 百分位数大。

90% 响应时间, 就是这个意思, 比如一个小时内 90% 的响应时间为 500ms, 表示是这个小时内所有请求该页面的响应时间中, 有 90% 的请求响应时间小于或等于 500ms

  • 计算方法

设一个序列供有 n 个数, 要求 (k%) 的 Percentile:

  • (1) 从小到大排序, 求(n-1)*k%, 记整数部分为 i, 小数部分为 j (这里 7*0.9=6.3, i 为 6, j 为 0.3)
  • (2) 所求结果=(1-j) 第 (i+1) 个数+j 第 (i+2) 个数 (这里为 0.7844+0.3994=889)

特别注意以下两种最可能考的情况:

  • (1) j 为 0, 即 (n-1)*k% 恰为整数, 则结果恰为第 (i+1) 个数
  • (2) 第 (i+1) 个数与第 (i+2) 个数相等, 不用算也知道正是这两个数。

1.2. 背景

在互联网业务蒸蒸日上的今时今日, 系统架构日渐复杂, 随着软件产品和工程团队的变革, 许多开源的监控工具应运而生, 其中有一些相当出名, 比如 Zabbix、Nagios 还有 StatsD。也有一些问题被大家不断讨论, 例如, 监控领域的开源工具 Zabbix 和 Nagios 哪个更好? StatsD 是否有可能取代 Zabbix 或 Nagios 成为系统监控的新标准?

1.3. StatsD 的诞生

作为一个大型的手工艺成品在线市场平台, Etsy 曾被纽约时报拿来和 eBay, Amazon 等比较。早在 2009 年, Etsy 正在奋力向外扩展。但是网站的可靠性却表现的差强人意。其原因主要与架构有关, Esty 的架构起源于 DevOps 之前的文化, 即开发人员, DBAs 和系统管理人员都专注于自己的筒仓, 且开发人员无法接触产品。在当时, 这就是开发和运营 Web 网站最常见的方式。

Kellan Elliott-McCrea 在 Etsy 担任工程部副总裁和首席技术官的五年内, 软件产品和工程团队都经历了翻天覆地的变革。工程团队变化最明显的方面是———展示。这种变革带来了许多开源工具, 其中有一些相当出名, 比如 StatsD, 一个从日志文件中生成指标, 抓取数据的聚合器。在过去几年中, StatsD 几乎可以说是最流行且实用的 DevOps 工具。

1.4. StatsD 简介

简单来讲, StatsD 就是一个简单的网络守护进程, 基于 Node.js 平台, 通过 UDP 或者 TCP 方式侦听各种统计信息, 包括计数器和定时器, 并发送聚合信息到后端服务, 如 Graphite。

StatsD 最初是由 Etsy 的 Erik Kastner 写的提供 Graphite/Carbon 指标的前端代理, 初衷是为了汇总和分析应用指标。它基于两大功能: 计数和计时。最开始使用 Node, 后来也实现了其他语言。通过 Statsd , 能通过特定语言的客户端检测应用程序的指标。基于个性化需求, 可以通过 Statsd 收集任何想要的数据。Statsd 通过发送 UDP 数据包来调用每个 Statsd 服务器, 下面我们来了解一下为什么选择 UDP 而不是 TCP。

1.5. 为什么使用 UDP?

前面也说了, StatsD 是通过 UDP 传输数据的, 那么有人会问为什么选 UDP 而不选 TCP 呢? 首先, 它速度很快。任何人都不想为了追踪应用的表现而减慢其速度。此外, UDP 包遵循「fire-and-forget」机制。所以要么 StatsD 接收了这个包, 要么没有。应用不会在意 StatsD 是运行、宕机还是着火了, 它单纯地相信一切运行正常。也就是说我们不用在意后台 StatsD 服务器是不是崩了, 就算崩了也不会影响前台应用。(当然, 我们可以通过图表追踪 UDP 包接收失败的情况。)

1.6. StatsD 的一些概念

为了更加了解 StatsD, 我们先来了解几个 StatsD 概念: buckets、values、flush interval。

1.6.1. Buckets

当一个 Whisper 文件被创建, 它会有一个不会改变的固定大小。在这个文件中可能有多个 buckets 对应于不同分辨率的数据点, 每个 bucket 也有一个保留属性指明数据点应该在 bucket 中应该被保留的时间长度, Whisper 执行一些简单的数学计算来计算出多少数据点会被实际保存在每个 bucket 中。

1.6.2. Values

每个 stat 都有一个 value, 该值的解释方式依赖于 modifier。通常, values 应该是整数。

1.6.3. Flush Interval

在 flush interval (冲洗间隔, 通常为 10 秒) 超时之后, stats 会聚集起来, 传送到上游的后端服务。
追踪所有事件是提高效率的关键。有了 StatsD, 工程师们可以轻松追踪他们需要关注的事务, 而无需费时地修改配置等。

1.6.4. StatsD 的延伸

收集和可视化数据是对服务器和应用做出明智决定的重要方式, StatsD 具有以下优点:

  • 简单——非常容易获取的应用程序, StatsD 协议是基于文本的, 可以直接写入和读取。
  • 低耦合性——基于后台程序运行的应用程序, 采取 UDP 这种「fire-and-forget」的协议, 收集指标和应用程序本身之间没有依赖。
  • 占用空间小——StatsD 客户端非常轻便的, 不带任何状态, 不需要的线程。
  • 普遍及支持多种语言——有基于 Ruby, Python, Java, erlang, Node, Scala, Go, haskell 等几乎所有语言的客户端。

2. StatsD 的使用小结

应用程序的监控是微服务中很重要的一环。监控主要包括四个方面的内容: 指标 (metrics) 的采集、存储、展示以及相应的报警机制。目前相关的解决方案以及工具非常多。今天就介绍一款用于采集数据的工具——statsd。
Statsd 最早是 2008 年 Flickr 公司用 Perl 写的针对 Graphite、datadog 等监控数据后端存储开发的前端网络应用, 2011 年 Etsy 公司用 node.js 重构。statsd 狭义来讲, 其实就是一个监听 UDP(默认)或者 TCP 的守护程序, 根据简单的协议收集 statsd 客户端发送来的数据, 聚合之后, 定时推送给后端, 如 graphite 和 influxdb 等, 再通过 grafana 等展示。

statsd 系统包括三部分: 客户端 (client)、服务器(server) 和后端(backend)。客户端植入于应用代码中, 将相应的 metrics 上报给 statsd server。statsd server 聚合这些 metrics 之后, 定时发送给 backends。backends 则负责存储这些时间序列数据, 并通过适当的图表工具展示。

2.1. 基本原理与概念

statsd 采用简单的行协议:

<bucket>:<value>|<type>[|@sample_rate]

2.1.1. bucket

bucket 是一个 metric 的标识, 可以看成一个 metric 的变量。

2.1.2. value

metric 的值, 通常是数字。

2.1.3. type

metric 的类型, 通常有 timer、counter、gauge 和 set 四种。

2.1.4. sample_rate

如果数据上报量过大, 很容易溢满 statsd。所以适当的降低采样, 减少 server 负载。
这个频率容易误解, 需要解释一下。客户端减少数据上报的频率, 然后在发送的数据中加入采样频率, 如 0.1。statsd server 收到上报的数据之后, 如 cnt=10, 得知此数据是采样的数据, 然后 flush 的时候, 按采样频率恢复数据来发送给 backend, 即 flush 的时候, 数据为 cnt=10/0.1=100, 而不是容易误解的 10*0.1=1。

2.2. UDP 和 TCP

statsd 可配置相应的 server 为 UDP 和 TCP。默认为 UDP。UDP 和 TCP 各有优劣。但 UDP 确实是不错的方式。

  • UDP 不需要建立连接, 速度很快, 不会影响应用程序的性能。
  • “fire-and-forget” 机制, 就算 statsd server 挂了, 也不会造成应用程序 crash。

当然, UDP 更适合于上报频率比较高的场景, 就算丢几个包也无所谓, 对于一些一天已上报的场景, 任何一个丢包都影响很大。另外, 对于网络环境比较差的场景, 也更适合用 TCP, 会有相应的重发, 确保数据可靠。
建议使用 UDP。TCP 还是有许多弊端的。

2.3. 安装

statsd 的安装非常简单。可选择两种方式: 克隆源码和 docker。

2.3.1. 克隆源码

首先需要安装 node 环境。不清楚的可以参考这篇文章。然后到 github 克隆代码, 修改相关配置启动即可。

git clone git@github.com:etsy/statsd.git
cd path/to/statsd
根据 exampleConfig 文件定义自己的配置文件
node stats.js path/to/config

这样 statsd server 就搭建成功了。

2.3.2. docker

用 docker 也是个好选择。

docker run -p 8125:8125 -p 8126:8126 --name statsd -d dockerana/statsd

statsd 默认监听 8125 来收集 udp 包。

可以通过 nc 指令测试数据收发。

echo "foo:1|c" | nc -w 1 -u 127.0.0.1 8125

2.3.3. 配置

statsd 提供默认的配置文件 exampleConfig.js。可以参考相应的注释按需配置, 接下来将简单介绍一些配置项。

  • 端口

默认为 8125 端口。

port: 8125
  • 后端

默认有 console、greaphite 等, 也有 influxdb 等 backend。console 的后端通常加上 prettyprint。可以同时配置多个 backends。backends 都要放在代码目录的 backends 目录下。

backends: ["./backends/console", "./backends/graphite"],
console: {
    prettyprint: true
}
  • flush interval

statsd 默认是 10s 执行一次 flush。可通过 flushInterval 设置, 单位 ms。

flushInterval: 2000  // 设为 2s
  • reload 配置

设置 automaticConfigReload, watch 配置文件, 如果修改, 即 reload 配置文件。默认为 true。(然而 reload 配置之后, 并没有生效。)

  • delete 系列配置

metric 上报时, 每次 flush 之后, 就会重置为 0(gauge 是保持原有值)。如果不上报这些空闲值, 可以通过 delete * 来设置。

deleteGauges: true,
deleteTimers: true,
deleteSets: true,
deleteCounters: true
  • percentThreshold

对于 timer 数据, 会计算一个百分比的数据(过滤掉峰值数据), 默认是 90%。可以通过 percentThreshold 修改这个值或配置多个值。

// 分别计算 50% 和 80% 的相关值
percentThreshold: [50, 80]

只列举了部分配置项, 具体请参考配置文件。

2.4. 指标 metric

statsd 有四种指标类型: counter、timer、gauge 和 set。

2.5. 计数器 counter

counter 类型的指标, 用来计数。在一个 flush 区间, 把上报的值累加。值可以是正数或者负数。

user.logins:10|c        // user.logins + 10
user.logins:-1|c        // user.logins - 1
user.logins:10|c|@0.1   // user.logins + 100
                        // users.logins = 10-1+100=109

2.6. 计时器 timer

timers 用来记录一个操作的耗时, 单位 ms。statsd 会记录平均值 (mean)、最大值(upper)、最小值(lower)、累加值(sum)、平方和(sum_squares)、个数(count) 以及部分百分值。

rpt:100|g

如下是在一个 flush 期间, 发送了一个 rpt 的 timer 值 100。以下是记录的值。

count_80: 1,
mean_80: 100,
upper_80: 100,
sum_80: 100,
sum_squares_80: 10000,
std: 0,
upper: 100,
lower: 100,
count: 1,
count_ps: 0.1,
sum: 100,
sum_squares: 10000,
mean: 100,
median: 100

对于百分数相关的数据需要解释一下。以 90 为例。statsd 会把一个 flush 期间上报的数据, 去掉 10% 的峰值, 即按大小取 cnt*90%(四舍五入)个值来计算百分值。
举例说明, 假如 10s 内上报以下 10 个值。

1,3,5,7,13,9,11,2,4,8

则只取 10*90%=9 个值, 则去掉 13。百分值即按剩下的 9 个值来计算。

$KEY.mean_90   // (1+3+5+7+9+2+11+4+8)/9
$KEY.upper_90  // 11
$KEY.lower_90  // 1

2.7. 标量 gauge

gauge 是任意的一维标量值。gague 值不会像其它类型会在 flush 的时候清零, 而是保持原有值。statsd 只会将 flush 区间内最后一个值发到后端。另外, 如果数值前加符号, 会与前一个值累加。

age:10|g    // age 为 10
age:+1|g    // age 为 10 + 1 = 11
age:-1|g    // age 为 11 - 1 = 10
age:5|g     // age 为 5, 替代前一个值
sets

记录 flush 期间, 不重复的值。

request:1|s  // user 1
request:2|s  // user1 user2
request:1|s  // user1 user2

2.8. statsd 客户端

statsd 的客户端已经支持多种语言的实现, 参看列表。nodejs 相关有几个推荐的: lynx、node-statsd 和 node-statsd-client, 使用都差不多, 星也差不多。以 (node-statsd-client)[https://github.com/msiebuhr/node-statsd-client] 为例:

const SDC = require('statsd-client'),
const sdc = new SDC({ host: 'localhost', port: 8125 });
//counter
sdc.counter('cnt', 10, 0.1); // 100/0.1=1000
sdc.increment('cnt', 10); // +10
sdc.decrement('cnt', 10); // -10
//gauge
sdc.gauge('rpt', 100);
sdc.gaugeDelta('rpt', -10);  // -10
//sets
sdc.set('ips', '1');
//timer
sdc.timing('rpt', 200);
//close
sdc.close()

2.9. 总结

  • 基本原理: statsd 是一个 udp 或 tcp 的守护进程。使用简单的行协议收集客户端的 metic 数据。statsd 使用 udp 的好处。
  • 安装及配置
  • metric 类型: counter、timer、gauge 和 sets。
  • statsd 的 node 客户端。

3. Metrics(指标)

3.1. Gauge(仪表) 可增可减的仪表盘

Gauge 代表一个度量的即时值。 当你开汽车的时候, 当前速度是 Gauge 值。 你测体温的时候, 体温计的刻度是一个 Gauge 值。 当你的程序运行的时候, 内存使用量和 CPU 占用率都可以通过 Gauge 值来度量。或者你也可以理解为统计瞬时状态的数据信息。

3.2. Counter(计数器) 只增不减的计数器

计数器。初始为 0。

3.3. Meters(计数器)

Meters 用来度量某个时间段的平均处理次数 (request per second), 每 1、5、15 分钟的 TPS。

统计结果有总的请求数, 平均每秒的请求数, 以及最近的 1、5、15 分钟的平均 TPS。

3.4. Histogram(直方图)

Histograms 主要使用来统计数据的分布情况, 最大值、最小值、平均值、标准偏差、中位数, 百分比 (75%、90%、95%、98%、99% 和 99.9%)。

3.5. Timer(计时器)

当我们既要统计 TPS 又要统计耗时分布情况。

Timer 用来测量一段代码被调用的速率和用时。实际上 Histogram 也能做到, 这个 Timer 就是基于 Histograms 和 Meters 来实现的。

3.6. Health Checks(健康检查)

Metrics 提供了一个独立的模块: Health Checks, 用于对 Application、其子模块或者关联模块的运行是否正常做检测。

3.7. Prometheus metrics

Prometheus 定义了 4 中不同的指标类型 (metric type): Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)。

在 Exporter 返回的样本数据中, 其注释中也包含了该样本的类型。例如:

# HELP node_cpu Seconds the cpus spent in each mode.
# TYPE node_cpu counter
node_cpu{cpu="cpu0",mode="idle"} 362812.7890625

more:

 类似资料: