当前位置: 首页 > article >正文

Prometheus Remote Write 在 Elasticsearch 中的摄取原理

作者来自 Elastic Felix Barnsteiner深入了解 Elasticsearch 对 Prometheus Remote Write 的实现protobuf 解析、指标类型推断、TSDS 映射以及数据流路由。Elasticsearch 最近新增了对 Prometheus Remote Write 协议的原生支持。你可以将 Prometheus或 Grafana Alloy直接指向一个 Elasticsearch 端点在无需任何中间适配器的情况下发送指标。本文将介绍当一个 Remote Write 请求到达时Elasticsearch 内部发生了什么。如果你想理解其实现方式、评估 Elasticsearch 与其他 Prometheus 兼容后端的对比或参与贡献这篇文章适合你。配套文章《使用 Remote Write 将 Prometheus 指标发送到 Elasticsearch》则介绍了设置和配置相关内容。请求生命周期从 HTTP 到索引文档Request lifecycle: from HTTP to indexed documents在深入之前先简单说明 Prometheus 的数据模型Prometheus 将所有指标值存储为 64 位浮点数并将指标名称视为一个普通的 label__name__。存储引擎本身并不区分一个值是 counter 还是 gauge。在理解 Elasticsearch 如何映射这些概念时请记住这一点。下面是一个 Remote Write 请求在 Elasticsearch 中的完整路径HTTP 层—— 端点接收压缩的 protobuf 负载检查索引压力使用 Snappy 解压并解析 protobuf WriteRequest。文档构建—— 每个时间序列中的每个 sample 都会被转换为一条 Elasticsearch 文档包含 timestamp、labels.* 和 metrics.* 字段。批量索引—— 单个请求中的所有文档通过一次 bulk 调用写入目标数据流。下面的章节将详细介绍每个阶段。HTTP 层HTTP layer该端点接受 application/x-protobuf 的 POST 请求。传入的请求体会按照与 bulk 索引 API 相同的索引压力限制indexing pressure limits进行跟踪。如果集群已经处于较高的索引负载下请求会在解析之前直接以 429 被拒绝。Prometheus 使用 Snappy 对 Remote Write 负载进行压缩。Elasticsearch 以流式方式对请求体进行解压而不会将其物化为一个连续的大块内存并且会根据可配置的最大值校验声明的解压后大小以防止解压炸弹攻击。解压后的数据体随后会被反序列化为 protobuf 的 WriteRequest。每个 WriteRequest 包含一个 TimeSeries 列表而每个 TimeSeries 包含一组 labels键值对以及一个 samples 列表时间戳 float64 值。文档构建对于每个时间序列中的每个 sampleElasticsearch 都会构建一个索引请求。下面是单条文档的示例结构{ timestamp: 2026-04-01T12:00:00.000Z, data_stream: { type: metrics, dataset: generic.prometheus, namespace: default }, labels: { __name__: http_requests_total, job: prometheus, instance: localhost:9090, method: GET, status: 200 }, metrics: { http_requests_total: 1027.0 } }所有来自 Prometheus 时间序列的 labels包括name都会被写入 labels.* 字段。指标值则写入 metrics.metric_name其中 metric_name 是namelabel 的值。如果时间序列中没有namelabel则会被完全丢弃其 samples 会被计为失败。非有限值NaN、Infinity、负 Infinity会被静默跳过。这也包括 Prometheus 的 staleness 标记它使用一个特殊的 NaN 位模式0x7ff0000000000002来表示某个时间序列已经消失。一个 sample一条文档你可能会疑惑将每个 sample 单独存储为一条文档是否会带来较大的存储开销尤其是在 labels 较多的情况下。一种常见的优化方式是将具有相同 labels 和时间戳的多个指标打包到同一条文档中。随着近期 TSDB 的改进这种优化已不再必要。Elasticsearch 已将单条文档的存储开销降低到一个程度使得将多个指标打包在一条文档中与将每个 sample 单独写入之间几乎没有差异。关于这些 TSDB 存储优化的详细介绍将在后续的专门文章中发布。批量索引Bulk indexing单个 Remote Write 请求中的所有文档会通过一次 bulk 请求发送到 Elasticsearch。每条文档的目标数据流为 metrics-{dataset}.prometheus-{namespace}并以仅追加append-only的 create 操作方式写入。指标类型推断Metric type inferenceRemote Write v1 并不会可靠地随 sample 一起传递指标类型。Prometheus 会通过单独的请求大约每分钟一次发送元数据类型、说明文本、单位而这些请求可能会被路由到与 sample 不同的节点。在分布式系统中等待元数据到达再缓冲 sample 并不现实因此 Elasticsearch 选择基于命名约定来推断类型。以 _total、_sum、_count 或 _bucket 结尾的指标名称会被映射为 counter其余则默认映射为 gauge。这是一个广泛使用的约定其他兼容 Prometheus 的后端系统也采用了类似方式。http_requests_total → counter request_duration_seconds_sum → counter request_duration_seconds_count → counter request_duration_seconds_bucket → counter process_resident_memory_bytes → gauge go_goroutines → gauge这种启发式方法可能出错。例如一个名为 temperature_total 的指标如果有人将一个 gauge 命名为这样会被错误地分类为 counter。目前的主要影响是一些 ES|QL 函数例如 rate()要求指标类型为 counter因此会拒绝被错误分类的 gauge。对于 PromQL我们计划取消这一限制使 rate() 无论声明类型如何都可以工作从而降低错误推断的影响。你可以通过创建 metrics-prometheuscustom component template 并使用自定义 dynamic templates 来覆盖默认推断。例如将所有 *_counter 字段视为 counterPUT /_component_template/metrics-prometheuscustom { template: { mappings: { dynamic_templates: [ { counter: { path_match: metrics.*_counter, mapping: { type: double, time_series_metric: counter } } } ] } } }自定义 dynamic templates 会与内置模板进行合并因此对于你未显式覆盖的指标默认的命名约定规则仍然适用。索引模板Elasticsearch 会安装一个内置的 index template用于匹配 metrics-.prometheus-。该模板使字段类型推断能够在无需手动 mapping 配置的情况下正常工作。启用了TSDS 模式这带来了基于时间的分区、优化的存储、去重能力以及随着数据老化进行降采样的能力。对于 labels 和 metrics 命名空间都使用了 passthrough 对象字段这有三个作用命名空间隔离labels 和 metrics 分别位于独立的对象命名空间labels.* 和 metrics.*因此名为 status 的 label 与名为 status 的 metric 不会发生冲突。维度识别labels 的 passthrough 对象被配置为 time_series_dimension: true这意味着 labels.* 下的每个字段都会自动被视为 TSDS 维度。当 Prometheus 发送一个包含新 label 的时间序列时该字段会自动成为一个维度无需显式定义 mapping。透明查询在 ES|QL 或 PromQL 中你不需要写 labels. 或 metrics. 前缀。例如可以直接使用 job 而不是 labels.job或使用 http_requests_total 而不是 metrics.http_requests_total。passthrough 映射会自动完成解析。针对 metrics 的动态推断会应用前面描述的命名约定规则。当一个新的指标名称首次出现时其字段 mapping 会在 metrics.* 下自动创建并带有正确的 time_series_metric 标注。启用了失败存储failure store。当文档索引失败例如由于 mapping 冲突——同一指标名称出现不兼容类型时这些文档会被路由到单独的 failure store而不是被静默丢弃。数据流路由三种 URL 模式会直接映射到对应的数据流名称URL patternData stream/_prometheus/api/v1/writemetrics-generic.prometheus-default/_prometheus/metrics/{dataset}/api/v1/writemetrics-{dataset}.prometheus-default/_prometheus/metrics/{dataset}/{namespace}/api/v1/writemetrics-{dataset}.prometheus-{namespace}这使你能够将来自不同 Prometheus 实例或不同环境的指标分隔到不同的数据流中。这种隔离带来几个好处生命周期隔离Lifecycle isolation你可以为不同数据流设置不同的保留策略。生产环境指标可能保留 90 天而开发环境指标可能只保留 7 天。访问控制Access control你可以将 API key 限定到特定数据流。例如一个团队的 Prometheus 实例写入 metrics-teamA.prometheus-prod而他们的 API key 只拥有该数据流的访问权限。查询性能Query performancePromQL 查询和 Grafana 仪表板可以限定在特定 index pattern 上避免扫描无关数据。错误处理与 Remote Write 规范Remote Write 规范定义了两类响应可重试5xx、429和不可重试4xx。Prometheus 会根据这一分类决定是否重试或丢弃失败请求。如果 bulk 请求中的任意 sample 因索引压力被拒绝Elasticsearch 会返回 429Too Many Requests。这会通知 Prometheus 进行退避backoff并使用指数退避策略重试。对于部分失败部分 sample 成功写入、部分失败响应中会包含汇总信息报告失败 sample 的数量并按目标索引和状态码分组同时附带每组的示例错误信息。没有namelabel 的时间序列会导致这些 sample 返回 400 错误。非有限值NaN、Infinity会被静默丢弃Prometheus 会收到成功响应并不会重试。NaN 最常见于 summary 分位数在尚未有观测值时例如在任何请求到达之前的 p99 延迟指标以及 staleness 标记。实际影响较小在大多数查询中缺失 sample 与 NaN 的行为类似因为 PromQL 的回溯窗口lookback window会以相同方式用最后已知值填充空缺。更重要的差异在于 staleness 标记这将在下文介绍。下一步Remote Write v2 及其未来Remote Write v2 目前仍处于实验阶段因此当前实现基于 v1。但 v2 解决了 v1 的多个局限性。元数据与 sample 同步Metadata alongside samplesv2 会在同一个请求中将 metric 类型、单位和描述信息与 time series 一起发送。这消除了对命名约定推断的依赖。原生 histogramNative histogramsv2 支持 Prometheus 原生直方图它可以自然映射到 Elasticsearch 的 exponential_histogram 字段类型。传统 histogram每个 bucket 一个 counter不仅冗长还会在查询时丢失精度而 native histogram 更紧凑且更精确。字典编码Dictionary encodingv2 用整数引用替代重复的 label 字符串从而显著减少高基数 label 集合的 payload 大小。创建时间戳Created timestampscounter 在 v2 中包含“创建时间”标记用于表示 counter 初始化时间。这使得后端能够比当前“数值下降即 reset”的启发式方法更准确地检测 counter 重置。除了 v2 之外还有两个未来方向正在考虑中。Staleness marker 支持当前 staleness markerPrometheus 在 scrape 目标消失时写入的特殊 NaN会被丢弃。如果支持它们将可以实现正确的 PromQL 回溯行为并避免“5 分钟残留数据”问题即已消失的序列仍出现在查询结果中。共享 metric 字段Shared metric field当前实现会为每个 metric name 创建一个独立字段例如 metrics.http_requests_total、metrics.go_goroutines 等。虽然可行但会导致字段映射数量随 metric 名称增长因此 Prometheus 数据流的字段上限被设置为 10,000。我们正在考虑另一种方案只在namelabel 中存储 metric 名称而将数值写入单个共享字段。这可以彻底避免字段爆炸问题也更贴近 Prometheus 的内部存储模型。这一方向属于提升 Elasticsearch metrics 存储效率与 Prometheus 兼容性的长期演进。可用性AvailabilityPrometheus Remote Write 端点已在 Elasticsearch Serverless 中可用无需额外配置。对于自管理集群可以使用 start-local 快速启动环境。如果遇到问题或有反馈可以在 Elasticsearch 仓库中提交 issue。原文https://www.elastic.co/observability-labs/blog/prometheus-remote-write-elasticsearch-architecture

相关文章:

Prometheus Remote Write 在 Elasticsearch 中的摄取原理

作者:来自 Elastic Felix Barnsteiner 深入了解 Elasticsearch 对 Prometheus Remote Write 的实现:protobuf 解析、指标类型推断、TSDS 映射以及数据流路由。 Elasticsearch 最近新增了对 Prometheus Remote Write 协议的原生支持。你可以将 Prometheus…...

用STM32的FSMC模拟8080并口驱动TFTLCD:以2.8寸屏为例的硬件级优化实践

STM32 FSMC驱动TFTLCD的硬件级优化:从时序解析到性能压榨 引言 在嵌入式显示领域,TFTLCD因其丰富的色彩表现和相对较低的功耗成为许多项目的首选。然而,当开发者从简单的Demo移植转向实际产品开发时,往往会遇到刷新率不足、CPU占用…...

深入理解STM32 DMA的FIFO与突发传输:从数据“堵车”到性能优化的关键配置

STM32 DMA性能调优实战:破解FIFO与突发传输的配置密码 在嵌入式开发中,当我们需要处理高速数据流(如音频采集、图像传输或网络数据包处理)时,DMA(直接内存访问)控制器往往成为系统性能的关键瓶颈…...

Dify医疗环境零信任配置全图解:从患者ID加密到API网关mTLS双向认证,含12个生产级YAML模板

第一章:Dify医疗安全配置的合规基线与威胁建模在医疗AI应用落地过程中,Dify平台的安全配置必须严格遵循《GB/T 35273—2020 信息安全技术 个人信息安全规范》《HIPAA Security Rule》及《医疗器械软件注册审查指导原则》等多维合规要求。合规基线并非静态…...

从生物神经元到人工神经网络:演化与深度学习革命

1. 从生物神经元到人工神经网络的演化之路"我们正在用硅基电路模拟碳基智慧的本质。"——Geoffrey Hinton1943年,当Warren McCulloch和Walter Pitts在《数学生物物理学通报》上发表那篇开创性论文时,他们可能没想到自己正在为一场持续至今的认…...

保姆级教程:在RV1126开发板上跑通LVGL官方Linux FB例程(含Makefile修改详解)

从零到一:RV1126开发板LVGL帧缓冲(FB)例程全流程实战 刚拿到RV1126开发板时,最令人兴奋的莫过于让炫酷的图形界面跑起来。LVGL作为轻量级嵌入式图形库,其官方Linux帧缓冲(FB)例程是验证显示功能的绝佳起点。但实际操作中,从代码下…...

用Arduino给LCD1602做个‘表情包’:手把手教你自定义5x7点阵字符(附完整代码)

用Arduino给LCD1602制作个性化表情包:从设计到实现的完整指南 那块1602液晶屏上闪烁的字符是否让你感到审美疲劳?其实只需几行代码,就能让这块经典显示屏焕发新生。想象一下,你的智能花盆能显示笑脸表示湿度正常,哭脸提…...

如何在3分钟内完成Windows系统激活:智能激活脚本完整教程

如何在3分钟内完成Windows系统激活:智能激活脚本完整教程 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows激活烦恼吗?KMS_VL_ALL_AIO是一款基于微软官方KMS…...

别再手动改代码格式了!用IntelliJ IDEA的CheckStyle插件,5分钟搞定团队代码规范

告别代码风格混乱:IntelliJ IDEA CheckStyle插件实战指南 当团队协作开发时,代码风格不一致往往成为效率杀手。想象一下:每次代码评审都要花半小时讨论缩进和命名规范,合并分支时因为格式问题产生大量冲突,接手老项目时…...

C语言学习笔记 - 5.C概述 - C的应用领域

本笔记基于郝斌-C语言自学入门教程整理,配套参考教材为谭浩强《C程序设计(第五版)》,适配VSCode C/C开发环境,核心梳理C语言的核心应用场景,明确C语言的适用边界与不可替代的优势领域。一、C语言应用领域总览C语言的核心应用场景&…...

[具身智能-406]:硅基觉醒:大模型“破壁”的三条路径,每天,这个世界上无数的生物人,在这三条主线,为硅基智能的极速的进化在孜孜不倦的努力。

让大模型摆脱“缸中之脑”和囚徒困境的三种路径:或连接数字世界的现有软件工具,即"智能体",即硅基智能在数字空间的野蛮扩张,所到之处,收割原先的数字世界劳动者,寸草不生。或连接模拟物理世界的…...

如何快速调整任何窗口大小:WindowResizer终极免费窗口调整工具指南

如何快速调整任何窗口大小:WindowResizer终极免费窗口调整工具指南 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 还在为那些无法拖拽大小的应用程序窗口而烦恼吗&…...

wireshark抓包看ip协议

注意:Wireshark 中没有单独一个叫做“IP”的协议条目。在 Wireshark 的 “Protocol” 列里,你永远不会看到一个孤零零的 IP 包。你看到的总是 TCP、UDP、ICMP、ARP 等。但这并不意味着 IP 协议不存在,恰恰相反,IP 协议是所有这些数…...

激活函数可视化对比:用Python和Matplotlib亲手绘制sigmoid、tanh、ReLU及其梯度图

激活函数可视化实战:用Python绘制并解析神经网络核心组件 在深度学习的世界里,激活函数如同神经网络的"灵魂",它们决定了神经元是否应该被激活以及激活到什么程度。对于初学者来说,理解这些函数的特性往往停留在数学公式…...

别再折腾Docker了!Windows本地用MSI安装Redis 5.0.14,5分钟搞定Spring Boot集成

Windows开发者福音:5分钟极速部署Redis 5.0.14与Spring Boot无缝对接 Redis作为高性能键值数据库,早已成为现代应用开发的标配组件。但对于Windows平台的开发者而言,环境配置往往成为拦路虎——Docker占用资源、虚拟机笨重复杂、源码编译又容…...

STC15W104单片机8脚4路2262 1527解码输出程序-带学习功能与掉电储存功能

STC15W104单片机8脚4路2262 1527解码输出程序,带学习功能,掉电储存。老铁们今天咱们搞点硬核的!最近在玩STC15W104这个8脚小钢炮,折腾出个支持1527/2262编码的万能遥控解码器。核心功能就三点:自动学习遥控器、掉电记忆…...

AndroidPdfViewer打印功能完整指南:3步实现PDF文档打印

AndroidPdfViewer打印功能完整指南:3步实现PDF文档打印 【免费下载链接】AndroidPdfViewer Android view for displaying PDFs rendered with PdfiumAndroid 项目地址: https://gitcode.com/gh_mirrors/an/AndroidPdfViewer 想要为你的Android应用添加PDF打印…...

Day05:大模型安全与合规科普笔记:守护AI时代的数据安全防线

文章目录大模型安全与合规科普笔记:守护 AI 时代的数据安全防线引言:AI 时代的安全挑战一、数据隐私:涉密数据的安全防护1.1 涉密及客户数据必须脱敏加密的原因1.2 严禁直接传入公共大模型的影响1.3 数据脱敏和加密的技术原理与实施方式二、内…...

STM32F407ZGT6高级定时器驱动二自由度舵机云台:从PWM原理到安装校准全解析

1. PWM信号与舵机控制原理 舵机的核心控制原理其实就像我们平时用遥控器调电视机音量一样简单。想象一下,当你按下音量键时,遥控器会发送一串特定长度的脉冲信号,电视芯片根据这个脉冲宽度来决定音量大小。舵机的工作原理也类似,只…...

大疆无人机开源项目实战:用Eclipse Paho库搞定MQTT双通道通信(TCP vs WebSocket)

大疆无人机开源项目实战:用Eclipse Paho库搞定MQTT双通道通信(TCP vs WebSocket) 当开发者基于大疆无人机开源项目进行二次开发时,通信协议的选择往往成为影响系统性能的关键因素。MQTT作为轻量级物联网协议,其传输层的…...

从麦克风阵列到声源坐标:手把手实现Python版SRP-PHAT定位(含代码)

从麦克风阵列到声源坐标:手把手实现Python版SRP-PHAT定位(含代码) 在智能音箱、会议系统甚至机器人听觉领域,声源定位技术正悄然改变人机交互的方式。想象一下,当你说出"打开客厅灯"时,设备不仅能…...

RocketMQ控制台查不到生产组?别慌,这可能是Producer的‘隐身术’

RocketMQ生产组"隐身"现象全解析:从生命周期到持久化配置 第一次使用RocketMQ控制台时,很多开发者都会遇到这样的困惑:明明用示例代码成功发送了消息,却在控制台的"生产者"列表里找不到对应的生产组信息。这就…...

Vite中如何配置自定义ESLint规则?(2026 Vite全新配置教程 全程避坑,亲测有效)

在 Vite 项目中配置自定义 ESLint 规则,主要分为 安装依赖、创建配置文件 和 (可选)集成到开发服务器 三个核心步骤。以下是详细指南: 第一步:安装必要的 ESLint 依赖 首先,你需要安装 ESLint 核心包以及针…...

Java项目Loom化实战:3步完成Spring WebFlux与虚拟线程深度整合(含生产级架构图)

第一章:Java项目Loom响应式编程转型指南Project Loom 为 Java 带来了轻量级虚拟线程(Virtual Threads)和结构化并发模型,与响应式编程范式(如 Project Reactor 或 R2DBC)并非互斥,而是可协同演进…...

特征值与特征向量:从数学原理到机器学习实践

1. 特征值与特征向量入门:从几何直观到机器学习应用当我第一次接触特征值和特征向量时,那些抽象的数学公式让我头疼不已。直到有一天,我在处理图像压缩问题时突然意识到:原来这些概念就藏在我们日常的机器学习任务中!今…...

构建智能聊天机器人的核心技术架构与实践

1. 构建终极AI聊天机器人的核心思路 在当今人机交互领域,AI聊天机器人已经从简单的问答工具进化为具备复杂对话能力的智能体。一个真正优秀的聊天机器人需要融合自然语言处理、上下文理解、个性化响应和持续学习四大核心能力。我在过去三年里主导过7个不同行业的对话…...

Gerbv终极指南:从新手到专家的PCB设计验证全流程实战

Gerbv终极指南:从新手到专家的PCB设计验证全流程实战 【免费下载链接】gerbv Maintained fork of gerbv, carrying mostly bugfixes 项目地址: https://gitcode.com/gh_mirrors/ge/gerbv 你是否曾因Gerber文件显示异常而耽误PCB生产进度?是否在多…...

Switch模拟器:Ryujin模拟器教程

下载配置模拟器前需要先安装游戏运行库,显卡驱动正常 龙神模拟器官网:https://ryujinx.org/ switch模拟器的区别 Ryujinx【龙神模拟器】兼容性更好,刚出来的游戏也能运行,但由于它以前只支持OpenGL,所以帧率较低&am…...

告别PWM和ADC:手把手教你用Arduino解析汽车传感器SENT协议(附代码)

告别PWM和ADC:手把手教你用Arduino解析汽车传感器SENT协议(附代码) 在汽车电子领域,传感器数据的可靠传输一直是工程师们面临的挑战。传统的PWM和ADC方式虽然简单,但存在分辨率低、抗干扰能力弱等局限。而SENT协议作为…...

Quartus安装路径踩坑实录:为什么你的软件一打开就闪退?

Quartus安装路径避坑指南:从闪退根源到系统级解决方案 第一次双击Quartus图标时,那种期待与兴奋很快被闪退的黑色窗口浇灭——这几乎是每位FPGA初学者的必经之路。我至今记得实验室里那位研究生对着不断消失的启动界面摔鼠标的场景,而问题的根…...