vmagent如何快速采集和转发Metrics
vmagent如何快速采集和转发Metrics
本文介绍了vmagent的设计细节,参考自:vmagent-how-it-works
VictoriaMetrics agent是一个轻量级工具,用于采集不同源的指标。vmagent可以在转发指标前(通过"relabeling")定制指标(降低基数、流聚合、去重等)。
第一步:通过API或抓取方式接收数据
HTTP API方式
并发限速
vmagent会通过一个并发限速器来读取数据,默认情况下,允许2x CPU core数目的并发insert请求(-maxConcurrentInserts
),如果所处环境的网络较慢,可以适当提高该值来优化数据传输速率。
如果一个请求阻塞超过1分钟(-insert.maxQueueDuration
),vmagent会返回503。
解压缩
在读取数据之后,vmagent需要根据请求头部的压缩类型来解压数据。vmagent支持3种remote write协议:Snappy、Zstandard(zstd)、Gzip。VictoriaMetrics的remote write协议采用的是zstd,相比其他方式,它可以降低2~4倍的网络流量,但需要额外约10%的CPU资源。
抓取方式
除通过HTTP API push方式获取数据外,vmagent还支持按照一定间隔从目标抓取指标。该方式与prometheus的pull方式相同:
config:
global:
scrape_interval: 10s
scrape_configs:
- job_name: "kubernetes-service-endpoints-slow"
scrape_interval: 5m
scrape_timeout: 30s
...
当数据加载到内存之后,有两种处理模式:流模式(以chunk为单位处理)和一次性处理模式。
流模式和一次性处理模式
这两种方式都各有优缺点。对于较小的数据,一次性处理更加高效;而对于较大的数据,使用流模式,以64 KB为单位处理数据,对资源来说更加友好。
默认情况下,当数据超过1MB(-promscrape.minResponseSizeForStreamParse
)时,vmagent会自动转换为流模式。
第二步:全局relabel和降低基数
现在,已经将原始数据转换为时序数据,vmagent需要将数据发送到远端存储。如果存储系统down(可能因为过载或出现故障),则vmagent会将数据发送到一个本地存储(默认启用),避免丢失该存储的数据。
如果禁用持久化队列,则直接丢弃数据。
为了在内存和性能方面保持高效,vmagent将数据拆分为块(block),每个块有2个限制:10,000条样本(-remoteWrite.maxRowsPerBlock
)或100,000个labels(通常是10倍的采样量)。
当一个时序块就绪后,会引入一个全局采样限速器来控制vmagent每秒可以采集的样本数(-maxIngestionRate
),默认没有限制。
高基数时序数据会对远端存储造成压力。为此,可以通过-remoteWrite.maxHourlySeries
和 -remoteWrite.maxDailySeries
控制一定周期内唯一时序数据的最大数目,超过限制的时序数据都将被丢弃,默认无限制。
第三步:全局去重和流聚合
这两种方式都是为了降低数据量,前者会导致数据丢失,后者采用的是一种数据聚合方式。
vmagent还可以去重,移除不需要的时序数据,目标是在一个特定的时间帧( -streamAggr.dedupInterval
)内仅保留最重要的数据点。例如将全局去重间隔设置为30s,则vmagent会:
- 在30s的窗口内,对于同一个时间序列,vmagent会仅保留最新的一条样本,即具有最高时间戳的样本。
- 如果两条样本具有相同的时间戳,则保留具有最高值的那条。
下一步是流聚合,这是一种在将指标发送到存储(远端或本地)之前对指标进行浓缩或总结的方式。
假设每秒采集的数据量比较大,对每条数据进行保存会占用大量空间,且会放慢查询速度,同时又不希望因为使用去重而导致数据丢失,此时可以采用流聚合。
例如下面流聚合方式:
- match: '{__name__=~".+_total"}'
interval: 5m
outputs: [total]
这种情况下,每5分钟会保存一个以"_total"结尾的指标点。因此,如果原始指标为some_metric_total
,则聚合后的指标为some_metric_total:5m_total
,这样就减少了数据量,且不会丢失重要的信息。
在启用流聚合后,vmagent会将数据发送到一个聚合器,聚合器具有自己的内存缓存,最终通过后台将缓存刷新到远端存储。
默认情况下,聚合器只会"偷取"并丢弃匹配聚合规则的时序数据,作为聚合器的输入。有如下两种模式:
-streamAggr.keepInput
:默认false。是否同时保存匹配和不匹配的input时间序列。如果为true,则都保存,为false,则按照-streamAggr.dropInput
处理。-streamAggr.dropInput
:默认false。是否丢弃所有input时间序列或仅丢弃匹配的时间序列,如果为true,则丢弃所有input 时间序列,为false,则仅丢弃匹配的input时间序列
这里需要注意的是,全局去重也会被应用到流聚合中,首先会在去重间隔内过滤数据,然后再将数据刷新到聚合器中。另外,若要同时使用去重和流聚合,则需要保证流聚合间隔要大于去重间隔,且为去重间隔的倍数。
此外还可以针对单条流设置去重。下面配置中,每分钟会聚合一次数据,且每30s的窗口内会执行去重过滤。
- match: '{__name__=~".+_total"}'
interval: 1m
outputs: [total]
dedup_interval: 30s
第四步:分片(sharding)和复制(replication)
至此处理的仍然是时序数据块(10,000条采样或100,000个labels)。下面需要考虑将数据发往远端存储,有两种策略:
- 复制:如果有多个远端存储 (
-remoteWrite.url
),则vmagent会将所有时序数据发往每个远端存储。 - 分片:如果设置了分片标识 (
-remoteWrite.shardByURL
),则不会将相同的数据发到每个存储系统中,而会切分这些数据,然后均匀分布到各个存储中。
对于分片,vmagent会针对每个时间序列,使用xxHash函数对组合的labels进行哈希计算,并用生成的64-bit哈希值来决定时间序列的归属。可以通过-remoteWrite.shardByURL.labels
指定用于计算分片的labels,以及使用-remoteWrite.shardByURL.ignoreLabels
来忽略计算分片的labels。
为了提高数据的可用性,可以启用分片复制(-remoteWrite.shardByURLReplicas
),即一个分片有多个副本。默认情况下。一个分片只有一个副本(无复制)。
第五步:对每个远端存储进行微调,四舍五入采样值
至此,可以使用分片或复制的方式将数据发往目的地。每个远端存储都对应一个管理器,称为"远端写入上下文"(remoteWriteCtx
),该上下文负责处理上面提到的所有操作,但仅针对单个存储。下面看下如何针对单个存储处理流聚合和去重:
- 首先针对单个远端存储执行relabel(
-remoteWrite.urlRelabelConfig
) - 执行流聚合 (
-remoteWrite.streamAggr.config
)。需要注意的是,不要混用全局流聚合和单存储流聚合 - 执行去重 (
-remoteWrite.streamAggr.dedupInterval
) - 最后为所有时序数据添加全局标签 (
-remoteWrite.label
),这些标签不受relabel的影响
另外vmagent还可以修改时序数据的值:
- 有效数字法(
-remoteWrite.significantFigures
):处理数字的精度,如12345.6789四舍五入到2位有效数字后变为12000 - 小数点位 (
-remoteWrite.roundDigits
):负责处理保留多少位小数点,如12345.6789四舍五入到小数点后2位后变为12345.68
第六步:刷新:Fast Queue
下一步将数据刷新到内存队列,称为"fast queue",它是一个混合系统,包含内存队列和基于文件的队列(持久队列)。fast queue用于保存由于远端存储跟不上采样速率而累积的样本。
在前面的处理中,vmagent使用snappy或zstd解压了时序数据,这里需要在将其发送到fast queue之间再次压缩。如果压缩之后的数据块大于8MB (-remoteWrite.maxBlockSize
),则vmagent会将其一切为二,如果仍然大于8MB,则继续递归拆分,直到达到8MB的限制。
内存队列
内存队列实际上是一个简单的golang buffer channel,FIFO队列。
当vmagent启动时,默认它会启动2倍CPU core的workers(goroutines,如果需要处理更多数据,可以通过-remoteWrite.queues
增加workers数目)。每个worker有5s的时间从内存队列读取数据,如果无法及时读取所有的数据,则剩余的数据会被刷新到文件队列。可以使用-memory.allowedPercent
(默认 60%) 或 -memory.allowedBytes
调节内存中应该保存的数据块数目。默认计算方式如下:
maxInmemoryBlocks := allowed memory / number of remote storage / maxRowsPerBlock / 100
// clamp(value, min, max)
clamp(maxInmemoryBlocks, 2, queue * 100)
记住,每个块包含10,000条样本(-remoteWrite.maxRowsPerBlock
),并确保内存中至少有2个块,且每个队列不超过100个块。
总结一下,什么时候数据会被刷新到磁盘?
- worker超时:如果一个worker无法在5s之内读取所有的内存数据,则剩余数据会被刷新到磁盘
- 积压的磁盘队列:如果磁盘队列中仍然有等待刷新到远端存储的数据,则新的块会被直接刷新到磁盘
- 内存限制:如果达到内存队列上限,则新块会被立即刷新到磁盘
基于文件的队列
刷新到磁盘的数据会被保存到-remoteWrite.tmpDataPath
指定的目录中(默认 /vmagent-remotewrite-data
)。
与内存队列相同,文件队列也有大小限制(-remoteWrite.maxDiskUsagePerURL
,默认0,即无限制)。如果达到上限,则vmagent会通过丢弃老的块来确保数据不会溢出。刷新到磁盘的数据会被保存到chunks文件中,每个chunk大小为512MB,chunk中的block包含两部分:
- Header:8字节的首部,表示block的大小
- Payload:实际的时序数据
const MaxBlockSize = 32 * 1024 * 1024 // 32 MB,块压缩上限为32MB
const DefaultChunkFileSize = (MaxBlockSize + 8) * 16 // over 512 MB
block的上限约为32MB,加8字节的首部,因此每个chunk文件最多可以有16个blocks。
这些chunk文件保存在/vmagent-remotewrite-data/persistent-queue/<url_id>_<url_hash>/<byte_offset>
目录中。
/tmpData/persistent-queue
│
└── 1_B075D19130BC92D7
├── 0000000000000000 # 512 MB chunk file
├── 0000000002000000 # 512 MB chunk file
├── 0000000004000000 # 512 MB chunk file
├── 0000000006000000 # 512 MB chunk file
├── flock.lock
└── metainfo.json
vmagent使用buffered writting方式写入chunk文件,buffer的大小取决于内存设定 (-memory.allowedPercent
, 默认 60%, 或 -memory.allowedBytes
),计算方式为:
// clamp(x, min, max)
bufferSize := clamp(allowed memory / 8 KB, 4 KB, 512 KB)
即,如果内存为2GB,则buffer大小为250KB,适用于4KB~250KB范围。
这样去重器会按照去重间隔将数据刷新到流聚合器,然后流聚合器会周期性地将数据刷新到fast queue。
第七步:刷新到远端存储
在vmagent启动时,它会启动一些worker来从fast queue(内存以及文件队列)拉取数据块,然后处理并尝试将这些数据发往远端存储。每个远端存储都有其特定数目的workers,通常为2倍的CPU core (-remoteWrite.queues
)。
每个worker会从队列拉取一个时序数据块,首先检查内存队列,如果为空,则检查文件队列,如果都为空,则等待新数据。
一旦获取到有效的块,worker会将它们发送到远端存储。如果vmagent需要停止(重启或重调度),则它会等待5s来结束请求发送。
vmagent使用限速器(-remoteWrite.rateLimit
)来限制发送到远端存储的数据速率,默认无限制。
vmagent如何快速采集和转发Metrics的更多相关文章
- Flink - metrics
Metrics是以MetricsGroup来组织的 MetricGroup MetricGroup 这就是个metric容器,里面可以放subGroup,或者各种metric 所以主要的接口就是注 ...
- 《ServerSuperIO Designer IDE使用教程》-2.与硬件网关数据交互,并进行数据级联转发,直到云端。发布:v4.2.1版本
v4.2.1 更新内容:1.重新定义数据转发文本协议,使网关与ServerSuperIO以及之间能够相关交互数据.2.扩展ServerSuperIO动态数据类的方法,更灵活.3.修复Designer增 ...
- 使用日志服务进行Kubernetes日志采集
阿里云容器服务Kubernetes集群集成了日志服务(SLS),您可在创建集群时启用日志服务,快速采集Kubernetes 集群的容器日志,包括容器的标准输出以及容器内的文本文件. 新建 Kubern ...
- 采集并分析Nginx访问日志
日志服务支持通过数据接入向导配置采集Nginx日志,并自动创建索引和Nginx日志仪表盘,帮助您快速采集并分析Nginx日志. 许多个人站长选取了Nginx作为服务器搭建网站,在对网站访问情况进行分析 ...
- 利用Metrics+influxdb+grafana构建监控平台(转)
转自http://www.jianshu.com/p/fadcf4d92b0e 这里再配合Influxdb和Grafana可以构建一个非常漂亮的实时监控界面. Grafana监控界面 采集数据(Met ...
- Runtime 运行时之一:消息转发
解释一 上一篇文章咱们提到了Runtime的消息传递机制,主要围绕三个C语言API来展开进行的.这篇文章我将从另外三个方法来描述Runtime中另一个特性:消息转发机制. 一.消息转发机制 当向某个对 ...
- 微服务监控之二:Metrics+influxdb+grafana构建监控平台
系统开发到一定的阶段,线上的机器越来越多,就需要一些监控了,除了服务器的监控,业务方面也需要一些监控服务.Metrics作为一款监控指标的度量类库,提供了许多工具帮助开发者来完成自定义的监控工作. 使 ...
- 用js采集网页数据并插入数据库最快的方法
今天教大家一个快速采集网站数据的方法,因为太晚了,直接上例子,这里以采集易车网的产品数据为例. 思路:利用js获取网页数据并生成sql命令,执行sql命令把采集的数据插入数据库. 1.用谷歌浏览器或者 ...
- kubernetes pod的弹性伸缩———基于pod自定义custom metrics(容器的IO带宽)的HPA
背景 自Kubernetes 1.11版本起,K8s资源采集指标由Resource Metrics API(Metrics Server 实现)和Custom metrics api(Promet ...
- AMS 新闻视频广告的云原生容器化之路
作者 卓晓光,腾讯广告高级开发工程师,负责新闻视频广告整体后台架构设计,有十余年高性能高可用海量后台服务开发和实践经验.目前正带领团队完成云原生技术栈的全面转型. 吴文祺,腾讯广告开发工程师,负责新闻 ...
随机推荐
- .NET云原生应用实践(一):从搭建项目框架结构开始
开篇 很早之前就想做一套案例,介绍.NET下如何从零开始搭建一个云原生的应用程序.不过这个话题有点大,会要包含很多内容.我本打算从新建一个ASP.NET Core Web API应用程序开始介绍,但又 ...
- python安装sklearn
安装sklearn这个包,首先要安装三个依赖包,如图划红线的部分. 要找这三个包,我们都可以登录:https://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy 这 ...
- 自定义指令 v-imgerror 当图片的 src 资源 无效 就替换 默认的 src 显示图片
// 回顾自定义指令 // 作用 : 自定义一些对dom操作的快捷指令 // 前提:指令就是用来操作 dom (v-if /v-show/v-for ....) // 语法:Vue.directive ...
- Kali Linux 各版本开启ssh 服务
Kali Linux 各版本开启ssh 服务 2019版kali Linux SSH链接办法 修改kali关于SSH服务默认配置并重启SSH服务,步骤如下: 打开sshd_config文件 leafp ...
- 云原生周刊:Flux 2.3 发布 | 2024.5.20
开源项目推荐 kubeinvaders kubeinvaders 专为 Kubernetes 用户设计.它提供了一种有趣而交互式的方式来探索和可视化您的 Kubernetes 集群.通过类似游戏的界面 ...
- 云原生周刊:6 项 K8s 成本控制策略 | 2023.7.17
开源项目推荐 Base Image Finder 当使用容器扫描工具来识别已知漏洞(CVE,或常见漏洞和暴露)时,可能很难理解漏洞在容器中的位置,以及如何缓解这些漏洞.通常,最简单.最有效的缓解方法是 ...
- P1762 偶数&杨辉三角
P1762 偶数&杨辉三角(天立OI) 解题思路 一.结论法 杨辉三角形结论 第\(n\)行有\(n\)个数. 每行奇数个数必为\(2^k\)(\(k\)不是行数) 当行数恰为\(2^k\)时 ...
- javascript语法--for in、for of和forEach
首先看简单for循环效果,功能最基本,但可以实现所有循环功能 for (let i = 0; i < list.length; i++) { } 接下来看for in.for of和forEac ...
- 解决浏览器SSL缓存,自动将http跳转至https导致无法访问的问题
PHP交流群 656679284 为PHP广大爱好者提供技术交流,有问必答,相互学习相互进步! 这里汇总一下几大常见浏览器 HSTS 的关闭方法. Safari 浏览器 完全关闭 Safari 删 ...
- Blocked aria-hidden on an element because its descendant retained focus.
背景 vue 2.6.10 报错:Blocked aria-hidden on an element because its descendant retained focus. The focus ...