为啥我的网卡指标这么大?
有用户反馈,夜莺自带的监控大盘,查看 Linux 监控数据,发现网卡流量特别大,是不是 Categraf 采集的数据有问题?
图表用到了 net_bytes_recv 这个指标,这个指标的含义是:操作系统自启动之后,收到的 byte 总数,只是一个 counter 类型的值,通常我们不关注当前值,而是关注一段时间内的增量,或者每秒增量,所以看图时会使用 rate()
函数。
Prometheus 中的 rate()
函数,只能用于 counter 类型,即单调递增的指标,操作系统启动之后收到的 byte 总数,肯定是单调递增的,所以可以用 rate()
函数。那如果操作系统重启呢?重启之后,指标会从 0 开始重新计数,rate()
函数会自动处理这种情况。所谓的“自动处理”,姑且可以理解为:如果发现指标值变小了,就认为是重启了,就会发生 rate()
函数的重置。
让该用户查看 rate
函数里边的原始指标的数据:
可以看到,时间戳很不规律,按理说默认每 15s 采集一次,时间戳的差值应该稳定在 15s 左右,图上可以看到,一会 9s 上报一个值,一会 6s 上报一个值,显然是有问题的。那问题出在哪呢?
通常来讲,是因为有两台机器标识相同,即 ident
相同导致的。两个机器的网卡数据肯定是不同的,肯定是一个大一个小,采集频率都是 15s,于是,一会第一个机器上报数据,一会第二个机器上报数据,交错进行。这种情况在 Prometheus 看来,就会当做一台机器频繁重启,rate()
函数频繁侦测到 reset,于是就会把数据累加起来,导致流量特别大。
Counter 类型的数据 Reset 时的图例
下面引用几个动图,来演示 Counter 类型的数据 Reset 的情况。原文在 这里。
简单来看,就是发现 reset 了,就会把 reset 之前最后一个值,加到 reset 之后的所有值上。再进行 rate()
或者 increase()
计算。
下面是 rate()
计算的逻辑示例:
rate()
是取 time window 中的第一个值和最后一个值,做差值计算,然后再除以时间差,求的是一个斜率。实际上,真实的代码中更复杂,真实的代码中还要考虑缺点的情况。
下面是 irate()
计算的逻辑示例:
irate()
是取 time window 中的最后两个值,做差值计算,然后再除以时间差,所以相比 rate()
,irate()
更关注最新的变化,更敏感一些。
下面是 increase()
计算的逻辑示例:
increase()
是求给定 time window 的绝对增量,但是实际的监控数据点和给定的时间窗口不可能完全重合,所以 increase()
会有线性外推的逻辑。