PS: Prometheus 也是鄙人目前在看的内容,大家一起学习。
前言
我们一般怎么去看待 Prometheus
呢?我个人会偏向于 Prometheus
是一套完整的 监控体系 的解决方案。 Prometheus
的社区中的监控的生态有很多,甚至于 我们目前的开源的框架等都会适配 Prometheus
的 exporter
, 也正是 很多的 exporter 完美的解决了 Prometheus
监控体系的大而广。但是,如果 Prometheus
仅仅依赖于我们的本地的文件系统,对于自身的 稳定性而言显然是不合理的,这是因为:
如果说数据不存在过期的情况,那么最先到达瓶颈的一定是 内存 。因为
Prometheus
会把time series
先搁置到 内存里面,在做相应的 刷写操作,所以呢,如果说你的query
里面的series
比较多,那就完犊子了,不就 OOM 了吗。
因此 Prometheus
才有了 remote stoage
一说。我们目前使用的 remote storage
是 Cortex
, 使用 Cortex 的原因其实就一个: 可以分租户。当然,Cortex 还有其他的好处,比如说,集群模式,比如说,底层可以使用多种存储形式——Cassandra
(我们目前使用的)。
remote_write
这里呢,我们使用远程写,依然会存在 瓶颈,但是这个瓶颈是在 remote_write 的过程中发生的,我们看下。
这里呢,我们先看 Prometheus 官方文档里面的定义:
1 | url: <string> |
对于 capacity
,谷歌的解释是这个:
在阻止从 WAL 读取更多样本之前,每个分片要缓冲的样本数。 建议在每个分片中都具有足够的容量以缓冲多个请求,以在处理偶发性较慢的远程请求时保持吞吐量。
配置就这么多,大家也看的明白,我们再看看源码:
1 | // RemoteWriteConfig is the configuration for writing to remote storage. |
HTTPClientConfig
1 | type HTTPClientConfig struct { |
QueueConfig
1 | // QueueConfig is the configuration for the queue used to write to remote |
这里关于 QueueConfig
咋一看,没感觉出啥,我们现在来看看 这个 QueueConfig
里面的默认的配置:
1 | // DefaultQueueConfig is the default remote queue configuration. |
这里,我们看到 capacity
的配置说明:
每个分片在其通道中最多有500个待处理的样本,加上已入队的待处理样本。 从理论上讲,每个分片待处理的样本数应该只有600个左右。 以1000个分片计为600k。
可以看到 Prometheus
默认定义了 1000 个 queue
,batch size
为 100,预期可以达到 1M samples/s
的发送速率。Prometheus
输出了一些 queue
相关的指标,例如 failed_samples_total
, dropped_samples_total
,如果这两个指标的 rate
大于 0,就需要说明Remote Storage
出现了问题导致发送失败,或者队列满了导致 samples 被丢弃掉。 这里的问题就需要 我们的Remote Storage
进行联合的排查。如果是 Remote Storage
出现了问题,那么 Remote Storage
的数据获取上显然是不对的,这就需要有一个监控去监控到这里的数据变化。比如说,笔者这里的 Cortex
, 监控到的 Cortex-Distributor
的数据上,租户的数据很平稳,没有出现大的波动,这时候就要考虑下 是不是 Prometheus
本身的 瓶颈 了。
这样看来,我们就很好理解了为了我们的 Prometheus
在数据量大的情况下,出现很多的 failed_samples_total
的原因了,这里就是我们的 Prometheus 的一个远程写的 性能问题,这个问题的解决思路有两个:
- 扩大
capacity
: 保证 我们的队列处于 可用状态,这样就要求内存足够大 - 做分片: 简单的理解就是 并发 操作
- 加
Prometheus
机器,用 不同的Prometheus
采集不同的指标,这样,原来一个Prometheus
采集的指标分摊到了多个Prometheus
上,问题也会得到很好的解决。
分片的操作,其实还是比较麻烦的,这个等我国庆在看看。