prometheus采用pull模型而非push模型,因其适配云原生动态环境;正确使用counter、gauge、histogram指标类型;避免高基数label,确保指标语义清晰、类型准确、标签合理。

Prometheus 是一个以“拉取(pull)”为核心、专为云原生环境设计的时序数据库监控系统,不是通用日志或事件收集器,也不是传统 agent-based 的轮询工具——它靠目标自己暴露 /metrics 接口,由 Prometheus 主动 HTTP GET 抓取。
为什么用 pull 模型而不是 push?
因为容器 IP 频繁变化、服务生命周期短、网络策略限制多。push 模型需要每个客户端主动连到中心服务,容易因网络不通、重试堆积、连接数爆炸而失败;pull 模型则由服务端统一控制节奏、超时和重试,天然具备反向防火墙穿透能力,也更容易做采样限流和故障隔离。
- 典型错误:把 Prometheus 当成 StatsD 用,试图让业务代码调
pushgateway上报所有指标 → 导致高基数标签泛滥、时间序列暴增、TSDB 崩溃 - 正确姿势:长期运行的服务(如 API、MySQL)用 Exporter 或客户端库暴露
/metrics;仅 CronJob 等短任务才走pushgateway,且必须带唯一job和instance标签,并在下次推送前清理旧数据 - 注意:
pushgateway不是存储层,只是中转站,Prometheus 抓完即丢,不能替代 TSDB
指标类型选错,90% 的查询变慢或不准
Counter 和 Gauge 看似简单,但混用会导致 rate() 计算出荒谬结果,比如负值、跳变、归零。根本原因是 Counter 必须单调递增,而 Gauge 表示瞬时状态,二者语义不可互换。
- HTTP 请求总数必须用
counter(如http_requests_total),否则rate(http_requests_total[5m])会失效 - 内存使用量必须用
gauge(如node_memory_MemAvailable_bytes),若误定义为 counter,重启后数值归零将被rate()解释为“瞬间释放了 TB 内存” - 延迟类指标优先用
histogram而非summary:前者支持服务端聚合(sum(rate(http_request_duration_seconds_bucket[5m]))),后者只能客户端计算分位数,无法跨实例合并
Label 设计不当,是生产环境最常被低估的性能杀手
一个高基数 label(如 user_id="123456789" 或 request_id="abc-def-xyz")会让单个 metric 爆出数万时间序列,直接拖垮 Prometheus 内存与查询延迟,甚至触发 OOMKill。
- 禁止将唯一值、会话 ID、URL 路径全量作为 label;应提取稳定维度,比如把
/user/123/profile归一化为path="/user/{id}/profile" - 用
label_replace()在 PromQL 中动态重写 label,比在 Exporter 里硬编码更灵活安全 - 检查高基数:执行
count by (__name__) ({__name__=~".+"})查看哪些 metric 拥有最多时间序列;超过 10k 就该警惕
真正难的从来不是装上 Prometheus,而是让每条指标从诞生起就带着正确的类型、合理的 label、清晰的语义——这决定了后续所有告警、看板、容量分析是否可信。别等查不出根因时再回头改指标定义,那比重构服务还重。










