新闻详情

新闻详情

首页 / 资讯中心 / 详情

Prometheus Pushgateway实战:打通短命任务与批处理监控的必经之路

发布时间:2026/10/2 9:36:16来源:尧图网络
Prometheus Pushgateway实战:打通短命任务与批处理监控的必经之路
第一次把 Prometheus 搭好、看着 Grafana 上跳出第一张监控图的时候我是非常兴奋的。但没高兴多久就撞上一件尴尬事公司一堆凌晨跑的统计脚本、数据报表任务完全没办法接进监控体系。Prometheus 是出了名的“拉”模型服务端主动去抓取 /metrics 端点可这些批处理任务跑完就退出等 Prometheus 去拉的时候进程早就没了数据自然也无从谈起。后来在同事提醒下用了 Pushgateway才算把这个缺口彻底堵上。这篇文章我不打算只是把官方 README 翻译一遍而是结合我这几年实际部署和维护 Pushgateway 的经验把安装、配置、客户端推送方式、Prometheus 抓取参数以及真正用起来之后才会遇到的坑一次讲清楚。如果你是刚接触 Prometheus 生态想把定时任务、批处理脚本也纳入监控这篇文章可以直接帮你少走很多弯路。1. 为什么 Prometheus 这么强调“拉”模式却还需要一个“推送网关”1.1 拉取模型的死角短命任务和离线环境先理清一个最基础的问题Prometheus 的监控哲学是服务端主动拉取。被监控对象必须常驻运行并且暴露一个 HTTP 端点通常是 /metricsPrometheus 按固定周期比如 15 秒或 30 秒从这个端点读取指标。这种设计有很多好处抓取节奏由 Prometheus 掌控服务端可以随时调整周期被监控目标不需要知道 Prometheus 的地址也就不存在“往哪儿推”的配置问题。但拉取模式有一个天然死角生命周期极短的任务。一个批处理脚本可能只运行 1 秒钟跑完就退出端口根本来不及监听一个定时报表任务可能每 6 小时才运行一次Prometheus 的抓取周期不可能为了它压缩到毫秒级。这种情况下服务端永远不可能在任务存活期间发起一次成功的抓取。还有另一类场景任务运行在无法从 Prometheus 网络直达的机器上或者处于临时创建的容器里Prometheus 连地址都不知道。这些问题都指向同一个解决办法——需要一个常驻的中间代理替 Prometheus 接收短期任务的指标。1.2 Pushgateway 的本质不是推倒拉模式而是给拉模式补一个“聚合站”Pushgateway 的名字容易让人误以为它是把 Prometheus 变成“推”模式其实它的角色更像是快递集散中心批处理任务把指标通过 HTTP 推给 PushgatewayPushgateway 按 job 和 instance 维度把指标暂存在内存里然后 Prometheus 依然以它习惯的拉取方式把 Pushgateway 当作一个普通 target 抓走。整个链路是三级协作任务侧任务即将结束或运行过程中通过 PUT/POST 请求把一组 Prometheus 文本格式的指标发给 Pushgateway 的 HTTP 接口。Pushgateway 侧接收指标后给指标统一打上 job 和 instance 标签按分组存放并提供查询页面和接口。Prometheus 侧在 scrape_configs 里配置抓取 Pushgateway 的地址像抓取普通 exporter 一样拉取所有暂存指标。所以 Pushgateway 严格来说不是“推模式替代方案”而是“拉模式下的聚合节点”。它适合的场景很明确定时任务、批处理脚本、短生命周期作业、网络不可直达的环境。而不适合的场景也很明确凡是能长期运行并暴露 /metrics 的服务都不建议绕一道 Pushgateway——直接让 Prometheus 拉取原服务少一个中间环节就少一份单点风险。2. 安装部署实测二进制、Docker、systemd 三种方式2.1 官方二进制安装最快跑起来的方式Pushgateway 的官方二进制包在 GitHub Releases 页面就能找到。以 Linux amd64 为例下载解压后里面只有一个可执行文件没有任何依赖直接运行就能监听 9091 端口。cd /tmp wget https://github.com/prometheus/pushgateway/releases/download/v1.6.2/pushgateway-1.6.2.linux-amd64.tar.gz tar xzf pushgateway-1.6.2.linux-amd64.tar.gz sudo mv pushgateway-1.6.2.linux-amd64/pushgateway /usr/local/bin/版本号以你实际拿到的为准我这边写 1.6.2 只是举例。解压出来的目录里除了二进制就是 LICENSE 和 NOTICE没有配置文件——Pushgateway 的参数全部通过命令行 flag 传入这很适合用 systemd 托管。启动后验证一下浏览器或 curl 访问 http://localhost:9091/ 能看到一个简单的 Web 页面访问 /metrics 能看到 Pushgateway 自身的内置指标比如pushgateway_build_info。此时它虽然还没收到任何推送但已经是一个可用的聚合节点了。2.2 Docker 部署一条命令拉起服务如果监控环境本身已经容器化直接用官方镜像更省事docker run -d --name pushgateway -p 9091:9091 prom/pushgateway但是要注意默认启动方式下指标全部保存在进程内存里容器一重启之前所有任务推送的数据全部丢失。生产环境务必挂载持久化目录并指定 checkpoint 文件docker run -d --name pushgateway \ -p 9091:9091 \ -v /data/pushgateway:/data \ prom/pushgateway \ --persistence.file/data/pushgateway.data \ --persistence.interval5m--persistence.file指定状态落盘文件--persistence.interval表示每隔多久把内存中的指标全量写一次盘。注意这是“全量 checkpoint”而非增量日志数据量大的时候要考虑磁盘 IO 和文件大小。如果临时用不想落盘不带这个参数也能跑但一定要清楚重启即丢的后果。2.3 用 systemd 守护进程托管生产环境最稳的方式我生产环境用的是 systemd 方式。原因很简单Docker 方式在多副本、网络策略上都多一层复杂度而 Pushgateway 本身只是一个无状态 HTTP 服务systemd 足够还方便开机自启和崩溃恢复。先创建系统用户和持久化目录sudo useradd -r -s /bin/false prometheus 2/dev/null || true sudo mkdir -p /var/lib/pushgateway sudo chown prometheus:prometheus /var/lib/pushgateway然后写一个 unit 文件/etc/systemd/system/pushgateway.service[Unit] DescriptionPrometheus Pushgateway Afternetwork.target [Service] Userprometheus Groupprometheus ExecStart/usr/local/bin/pushgateway \ --persistence.file/var/lib/pushgateway/pushgateway.data \ --persistence.interval5m Restartalways RestartSec5 [Install] WantedBymulti-user.target启动并验证sudo systemctl daemon-reload sudo systemctl enable --now pushgateway sudo systemctl status pushgateway这里有个容易忽略的细节Restartalways保证进程崩溃时自动拉起。但由于有持久化文件重启后内存指标会从 checkpoint 恢复恢复窗口最多是persistence.interval期间的数据。也就是说5 分钟 checkpoint 一次极端情况下宕机会丢失最近 5 分钟内推送的指标。评估你的业务能否接受这个丢失窗口再决定要不要把 interval 调小。3. 推送、查询、替换与删除Pushgateway HTTP API 的核心操作3.1 用 curl 手动推送指标理解 API 语义的最好方式Pushgateway 的核心 API 路径是/metrics/job/JOB_NAME/instance/INSTANCE_NAME其中 instance 段可以省略。最经典的入门命令echo some_metric 3.14 | curl --data-binary - http://localhost:9091/metrics/job/some_job注意这里必须用--data-binary不能简单用-d。因为-d会忽略数据中的换行而 Prometheus 文本格式是按行解析的换行丢了指标就解析失败。推送之后再访问 http://localhost:9091/metrics就能看到这条指标被加上了jobsome_job标签。如果 URL 里写了 instance指标还会带上对应的 instance 标签。真实项目中极少只推一个指标。更完整的示例是带类型声明和多个标签的推送cat EOF | curl --data-binary - http://localhost:9091/metrics/job/etl_report/instance/192.168.1.10 # TYPE etl_rows_processed gauge etl_rows_processed 1024 # TYPE etl_duration_seconds summary etl_duration_seconds{phaseextract} 3.2 etl_duration_seconds_count{phaseextract} 1 EOF这里有个重要的约定推送内容里绝对不要自己写 job 或 instance 标签这两个标签只能通过 URL 路径指定。如果你在 body 里写了jobxxxPushgateway 会直接返回 400 拒绝因为它在把指标归入分组时会发现冲突。3.2 GET、PUT、POST、DELETE 分别意味着什么Pushgateway 对外暴露了四类操作语义差别非常关键方法路径行为语义GET/metrics查看全部暂存指标PUT/metrics/job/ [/instance/ ]整体替换该分组下的所有指标POST/metrics/job/ [/instance/ ]只更新本次提交中的指标组内其他指标保留DELETE/metrics/job/ [/instance/ ]删除该分组全部指标PUT 是幂等的同一个 job 下次再推送之前推的所有指标都会被清空只剩下本次提交的指标。这种语义非常适合“每个 job 只有一个推送方”的场景——任务每次运行结束推一组最新结果旧版本自然被覆盖不会堆积垃圾指标。POST 则是部分更新只有本次提交中出现的指标名被新增或覆盖其他指标原样保留。这个语义看起来灵活但也意味着如果同一个 job 被多个任务共用且它们都推不同的指标整个组的指标集合会不断膨胀时间一长全是历史残留。所以我在生产环境定了一条规矩Pushgateway 的分组要么按 job 划分一个任务一个独立 job要么按 instance 划分不同任务绝不共享同一个 job 组。能统一用 PUT 更好把每次推送当作一次全量上报。3.3 删除指标任务生命周期管理最重要的一步任务跑完指标该不该留在 Pushgateway我的答案是视情况而定。如果这个任务每次运行都要更新结果用 PUT 自然覆盖即可不需要删。但如果任务是“本次结束后一段时间内不需要了”或者任务本身代表一次临时操作及时删除才是正确姿势curl -X DELETE http://localhost:9091/metrics/job/etl_report/instance/192.168.1.10不带 instance 时删除整个 job 组curl -X DELETE http://localhost:9091/metrics/job/etl_report这里必须提醒DELETE 操作非常危险。没有任何二次确认一个请求就能清空整个分组的数据。之前我就遇到过同事误删监控组的情况好在 Grafana 会自动把数据缺口画出来否则很可能根本发现不了。后续你会看到我反复强调“Pushgateway 没有内置鉴权”这句强调的第一适用场景就是 DELETE。3.4 通过客户端库推送以 Python 为例实际项目里不可能每次都手动 curl任务脚本通常用客户端库推送。Prometheus 官方提供了 Go、Java、Python、Ruby 等语言的客户端这里以 Python 举例。from prometheus_client import CollectorRegistry, Gauge, pushadd_to_gateway registry CollectorRegistry() g Gauge(backup_last_success_unixtime, last backup finish timestamp, registryregistry) g.set_to_current_time() pushadd_to_gateway(localhost:9091, jobbackup, registryregistry)注意这里的pushadd_to_gateway对应的是 POST 语义也就是部分更新。如果你希望每次推送都清空这个 job 下的旧指标应该用push_to_gateway它对应 PUT 语义。两者一字之差行为完全不同。Go 客户端里对应的是Push()和PushAdd()Java 客户端的PushGateway类里也区分pushAdd()与push()理解这层对应关系换语言也不会踩坑。还有一点经验如果推送的指标值包含任务结束的 Unix 时间戳并以此判断“任务是否还在跑”务必通过set_to_current_time()或者显式传入当前时间千万不要在任务开始时就把“成功时间”推出去。否则任务还没跑完监控上已经显示“上一次成功”是刚刚这是典型的语义错误。4. Prometheus 抓取配置里最容易被忽略的 honor_labels 参数4.1 一个最简单的抓取配置Pushgateway 部署好了Prometheus 还要把它纳为抓取目标。配置放在scrape_configs下按普通的 static_config 写就行scrape_configs: - job_name: pushgateway honor_labels: true static_configs: - targets: [localhost:9091]看起来就这么几行但honor_labels: true这一项我见过太多人漏掉漏掉的后果非常隐蔽所有任务推上去的 job 和 instance 标签会全部错乱。4.2 为什么必须开 honor_labels先回顾一下 Prometheus 抓取流程中的标签冲突问题。Prometheus 在抓取任何 target 时都会自动给抓回的每条指标加上两个标签job值来自 job_name和instance值来自被抓取目标的地址。Pushgateway 里的指标本身又已经通过 URL 路径带上了任务指定的 job 和 instance。这样一来一条指标上就出现了两个来源的同一组标签。honor_labels参数就是用来决定这种冲突怎么处理。默认值是 false也就是“Prometheus 的 target 标签优先”被监控对象自带的 job、instance 标签会被强制覆盖为 target 的标签值。这在抓普通 exporter 时通常没问题因为 exporter 自身一般不会手动塞 job/instance 标签。但 Pushgateway 不一样它存在的意义恰恰就是把任务指定的 job/instance 标签传给 Prometheus。如果 honor_labels 不设为 true任务推送时在 URL 里精心指定的 job 和 instance 全都会被pushgateway和localhost:9091覆盖掉查询时你看到的 job 永远是 pushgateway根本分不清数据来自哪个批处理任务。当honor_labels: true时规则逆转Prometheus 会保留任务指定的 job/instance 标签作为指标的主 job/instance同时把 target 自带的 job/instance 标签改名为exported_job和exported_instance额外附加上去。所以在实际查询中你大概率会同时看到jobetl_report和exported_jobpushgateway两个标签前者是任务真实身份后者是抓取来源标识这是正常现象不是配置错乱。补一个查询技巧因为 Pushgateway 有多个 job 分组在 Grafana 面板上建议直接按 job 标签过滤而不是依赖 target 的 instance。用job定位业务用exported_instance定位是哪个 Pushgateway 节点抓来的两个维度互不干扰告警的时候非常好排查。4.3 抓取周期和数据量评估Pushgateway 的指标是所有批处理任务推送结果的汇总如果任务非常多这个 target 返回的数据可能比普通 exporter 大一个数量级。抓取周期我一般保持默认的 15s 或 30s不需要太频繁因为批处理任务本身不是高频更新。但如果单个 Pushgateway 上承载了几百个 job建议适当调大scrape_timeout否则一旦处理时间超过抓取超时Prometheus 会把这个 target 标记为 down连带所有任务的数据都在 Grafana 上断线。一个经验阈值几千条指标以内默认配置完全够用。如果到了几万条优先做分组拆分而不是死撑一个 Pushgateway。Pushgateway 本质上是单机内存存储没有内置集群能力规模上来之后单点瓶颈会非常明显。5. 真正用起来才会遇到的三个坑指标过期、分组冲突、无鉴权5.1 推上去的指标永远不会自动过期这是 Pushgateway 最反直觉的地方也是新手最容易中招的点。默认情况下任何推送到 Pushgateway 的指标都会一直保留在内存里或持久化文件里没有任何 TTL 机制。任务停止推送了昨天的指标今天还在且 Prometheus 抓到的依然是最新值。这会导致什么后果假设有一个每天凌晨 2 点跑的备份任务它在结束时推送backup_status 1。某天任务因为不可抗力没有运行但 Pushgateway 里依然躺着昨天那次成功的backup_status 1Prometheus 也不会主动发现异常。你在 Grafana 上看到的是一条持续稳定的水平线好像备份一直健康。这种“静止的数据”比数据丢失更可怕——它假装一切正常。解决办法不是期待 Pushgateway 增加过期机制而是靠两个手段配合第一任务在开始时主动清理自己的指标结束时再推送最终结果。这样如果任务没有正常结束Pushgateway 里自然没有本次的结果配合下面的陈旧告警就能发现。第二利用 Pushgateway 内置的push_time_seconds指标。这个指标记录了每个 job 最近一次成功推送的时间戳是一个 unix 时间。在 Prometheus 里写一条告警规则groups: - name: pushgateway_stale rules: - alert: PushgatewayJobStale expr: time() - push_time_seconds 600 labels: severity: warning annotations: summary: job {{ $labels.job }} 超过 10 分钟没有推送指标当任务超过 10 分钟没有推送这条告警就会触发。这是对付 Pushgateway 数据“假活”的最标准手段强烈建议一上来就配上。5.2 POST 合并带来的指标爆炸和覆盖问题前面表格里提过POST 是部分更新保留组内其他指标。这个设计的初衷是允许多个任务共享一个 job各推各的指标互不影响。但实际用起来共享几乎总会翻车。我见过一个真实案例两个团队共用一个jobbatch_jobA 团队用一个 instanceB 团队又用另一个 instance本来互不干扰。某天 B 团队在代码里把 URL 的 instance 写错了直接推到 A 团队的 instance 分组里而 A 团队用的又是 POST于是 B 团队的指标和 A 团队的指标混在一起同名指标被 B 覆盖成 B 的数值。A 团队排查了一下午最后才发现是“别人用了我的分组”。这是 Pushgateway 在设计上的天然弱点分组信息完全靠 URL 字符串约定没有所有权概念。我的建议非常明确不要跨团队共享同一个 job 或 instance每个任务、每个团队都使用独立的 job 路径。在此基础上所有推送一律用 PUT 语义保证幂等。只有一种情况我建议用 POST任务推的是带多标签的指标且你必须保留另一个脚本推的指标。但这种“必须共享”的场景越少越好。5.3 没有任何内置鉴权安全边界全靠自己Pushgateway 默认没有任何鉴权机制任何能访问 9091 端口的人都可以推送、查询、删除指标。这在内网环境里或许还能忍但只要暴露到了稍大一点的网络范围就是灾难。删除接口一个 curl 全部清空推送接口可以塞垃圾数据。我在生产环境做的防护措施有三层第一层坚决不把 Pushgateway 端口直接暴露到公网只在监控内网段开放访问。这是底线。第二层前置一层 Nginx 做 basic auth只允许知晓账号密码的监控系统访问。给一个参考配置片段server { listen 9092; location / { proxy_pass http://127.0.0.1:9091; auth_basic pushgateway admin; auth_basic_user_file /etc/nginx/htpasswd_pushgateway; } }Prometheus 抓取时在配置里带上用户名密码scrape_configs: - job_name: pushgateway honor_labels: true basic_auth: username: prometheus password: your-password static_configs: - targets: [localhost:9092]第三层在推送侧如果能控制来源 IP用防火墙限制只允许任务所在网段调用 9091 端口的 PUT/POST/DELETE。这点实现起来依赖具体环境但至少要在意识里明确Pushgateway 本身不是一个安全边界它只是一个工具安全策略必须叠加在外面。6. 把 Pushgateway 自身纳入监控以及更长远的设计思路6.1 别忘了监控 Pushgateway 自己Pushgateway 一旦成为批处理监控链路的必经节点它自己挂了就等于所有批处理任务全部失联。但讽刺的是很多人部署完就忘了监控它。好在 Pushgateway 自身暴露了完整的 Go 运行时指标直接用 Prometheus 拉它的 /metrics 就能监控。除了基础的up探活和 Go 进程指标我重点盯两个自定义指标每个 job 的push_time_seconds最大值和当前时刻的差值这直接反映任务链路是否健康以及 Pushgateway 当前暂存的指标总量在 Prometheus 里可以用count(push_time_seconds)或者查看pushgateway_..._metrics相关内置指标估算如果这个数字突然暴涨大概率是某个任务的脚本写了个死循环在狂推。6.2 扩展思考Pushgateway 是不是唯一解老实说Pushgateway 解决了“短命任务无法被拉取”的问题但它的设计也存在不少历史包袱无 TTL、单点存储、无鉴权、分组靠自觉。如果你正在搭一套全新的监控体系其实还有两个替代方案值得对比。一个是用 node_exporter 的 textfile collector。批处理任务把结果写成文本文件放到指定目录node_exporter 周期性读取并暴露给 Prometheus。这个方案天然没有“推”的概念指标生命周期跟随文件是否更新缺点是必须依赖一台长期运行的机器上的 node_exporter。另一个是直接走 Prometheus remote write 到后端存储但这对任务侧的配置要求偏高适合已经有成熟 TSDB 体系的团队。我的个人倾向是小规模、简单场景Pushgateway 依然是省心选择但一定配上陈旧告警和访问控制如果团队规模大、任务数量多早点设计好分组规范和监控权限边界比后期治理成本低得多。就目前而言我自己维护的 Pushgateway 跑了大半年最深的体会是它真正难的不是安装而是用起来之后的规范和纪律。指标过期判断、分组命名、删除权限、推送语义每一件都需要在团队层面定好约定。把这些约定落到监控告警里Pushgateway 才能成为一个可靠的桥梁而不是监控链条上新的盲点。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

JS读取txt文件避坑指南:编码、大文件与流式处理 2026/10/2 10:21:51

JS读取txt文件避坑指南:编码、大文件与流式处理

上周帮同事看一个"小问题":一个纯前端的统计小工具,让用户选一个 txt,页面把内容读出来做个词频统计。功能写完了,本地双击 HTML 就跑,文件一选,页面上出来一堆问号。他以为是 FileReader 坏了&a…

阅读更多 →
轻量级自托管LLM API基准测试平台 2026/10/2 10:21:51

轻量级自托管LLM API基准测试平台

1. 项目概述:为什么你需要一个“能装进U盘”的LLM基准测试平台最近两周,我连续帮三个不同团队做模型服务选型——一家做金融文档摘要的创业公司、一所高校的NLP实验室、还有一家给制造业客户部署边缘AI质检系统的集成商。他们提的问题高度一致&#xff1…

阅读更多 →
Unity SpriteAtlas图集:2D合批、Draw Call与内存权衡 2026/10/2 10:21:51

Unity SpriteAtlas图集:2D合批、Draw Call与内存权衡

1. 从一次Draw Call暴涨说起:SpriteAtlas真正解决的到底是什么问题前阵子接手一个2D项目做性能优化,打开Profiler的Frame Debugger一看,一个看起来干干净净的背包界面,Draw Call稳定在80多。美术用的全是零散的小图,每…

阅读更多 →
WANGEDITOR集成实战:解决初始化报错并实现公众号素材导入 2026/10/2 10:21:51

WANGEDITOR集成实战:解决初始化报错并实现公众号素材导入

1. 为什么金融平台需要"微信公众号素材导入"这样的能力 干金融平台内容系统的人应该都有过这种经历:运营同事手里有一篇写好的投教文章,已经在自家公众号里发过一篇排版精美的版本,现在要把它同步到平台内部的资讯中心、产品公告栏…

阅读更多 →
C/S与B/S架构区别:通信、状态管理与选型实践 2026/10/2 10:21:51

C/S与B/S架构区别:通信、状态管理与选型实践

面试或者技术评审上,"C/S架构和B/S架构有什么区别"这个问题出现的频率高得离谱。绝大多数人能答出"C/S是客户端/服务器,B/S是浏览器/服务器",再往下追问通信方式怎么定、状态放哪儿、版本怎么兼容、断网了怎么办&#xf…

阅读更多 →
LLMs之Agent之Cowork:把 Claude Code 的文件读写能力交给非开发者——用 Connectors 与 Skills 在本地文件夹里跑通读取、编辑与创建,TaoToken 统一 K 2026/10/2 10:21:45

LLMs之Agent之Cowork:把 Claude Code 的文件读写能力交给非开发者——用 Connectors 与 Skills 在本地文件夹里跑通读取、编辑与创建,TaoToken 统一 K

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉