4. Target 抓取生命周期:从服务发现到抓取、抓取协议(HTTP/HTTPS)、抓取超时与重试机制

Prometheus 通过 Pull 模式主动从 Target 拉取指标数据。一个完整的抓取生命周期涉及服务发现、目标实例化、协议协商、数据拉取、超时控制与重试等多个阶段。理解这一生命周期是诊断抓取故障、优化采集性能的基础。

4.1 抓取生命周期总览

从服务发现到指标入库,一个 Target 的抓取过程可划分为以下关键阶段:

  1. 服务发现:通过配置的服务发现机制(如 Kubernetes、Consul、DNS、文件发现)获取目标列表。
  2. 目标实例化:将发现的目标转换为 __address__、__metrics_path__、__scheme__ 等内部标签,并应用 relabel 规则。
  3. 健康检查与协议协商:根据 scheme(HTTP/HTTPS)建立连接,可选 TLS 握手。
  4. 指标拉取:向 <scheme>://<address><metrics_path> 发送 GET 请求,读取响应体。
  5. 超时控制:在 scrape_timeout 内完成 DNS 解析、连接、TLS 握手、请求发送和响应读取。
  6. 数据解析与重试:解析响应体为 Prometheus 文本格式,若失败则根据配置决定是否重试。
  7. 样本入库:将解析后的样本追加到 TSDB 的 Head 块。
Target 抓取生命周期流程图 1. 服务发现 2. 目标实例化 3. 协议协商 4. 指标拉取 5. 超时控制 6. 数据解析与重试 7. 样本入库 重试(scrape_retries) 关键说明: • 超时控制贯穿阶段 3-5:DNS 解析、TCP 连接、TLS 握手、请求发送、响应读取均在 scrape_timeout 内完成。 • 重试仅在阶段 6 解析失败时触发,不会重新执行阶段 1-5。 • 若阶段 5 超时,阶段 6 直接跳过,标记为 scrape_timeout 错误。 • 阶段 7 入库失败(如样本重复、时间戳异常)不会触发重试。 • 每个阶段都有对应的 Prometheus 指标暴露,可用于故障定位。

4.2 抓取协议:HTTP 与 HTTPS

Prometheus 使用标准 HTTP/HTTPS 协议与 Target 通信。协议选择由 scheme 配置项控制,默认值为 http。

配置项 默认值 说明
scheme http 可选 http 或 https,决定使用明文还是 TLS 加密连接
tls_config 空 HTTPS 模式下可配置 CA 证书、客户端证书、跳过验证等参数
metrics_path /metrics 抓取路径,与 scheme 和 address 拼接为完整 URL

协议选择最佳实践:

  • 生产环境建议使用 HTTPS 加密传输,防止指标数据在传输过程中被窃听或篡改。
  • 使用 HTTPS 时务必配置 tls_config 中的 ca_file 或 insecure_skip_verify: false,避免中间人攻击。
  • 对于 Kubernetes 环境,Kubelet 的 /metrics/cadvisor 端点通常使用 HTTPS,需配置正确的 CA 证书。

4.3 抓取超时机制

超时控制是抓取生命周期中最关键的故障防护机制。Prometheus 通过 scrape_timeout 参数控制单次抓取的最大耗时。

4.3.1 超时配置与默认值

参数 默认值 作用范围
scrape_timeout 10s 单次抓取的总超时(包括 DNS、TCP、TLS、请求、响应)
scrape_interval 1m 两次抓取之间的间隔,必须大于 scrape_timeout

重要约束:scrape_timeout 必须小于 scrape_interval,否则会导致抓取队列积压、样本时间戳混乱。官方建议 scrape_timeout 不超过 scrape_interval 的 80%。

4.3.2 超时发生的阶段与表现

超时可能发生在以下任意阶段,每个阶段的超时表现不同:

  • DNS 解析超时:无法解析 Target 主机名,日志中出现 dial tcp: lookup xxx: i/o timeout。
  • TCP 连接超时:无法建立 TCP 连接,日志中出现 connect: connection timed out。
  • TLS 握手超时:HTTPS 模式下 TLS 协商失败,日志中出现 tls: handshake timeout。
  • 请求发送超时:数据发送阶段卡住,通常由 Target 端负载过高或网络拥塞导致。
  • 响应读取超时:Target 返回数据过慢或数据量过大,导致读取时间超过剩余超时窗口。

4.4 重试机制

Prometheus 的重试机制相对简单,旨在处理瞬态故障而非持续性问题。

4.4.1 重试配置

参数 默认值 说明
scrape_retries 0 抓取失败后的重试次数,0 表示不重试
scrape_retry_delay 5s 重试之间的等待间隔

4.4.2 重试触发条件

重试仅在以下场景触发:

  • HTTP 状态码非 200:如返回 500、503 等服务器错误。
  • 响应体解析失败:返回的数据不是有效的 Prometheus 文本格式或 Protobuf 格式。
  • 网络层错误:如连接重置、TLS 证书错误等。

以下场景不会触发重试:

  • 超时:超时后直接标记为失败,不重试。
  • HTTP 4xx 错误:如 401、403、404,表示客户端错误,重试无意义。
  • 样本入库失败:解析成功但写入 TSDB 失败。

重试策略建议:

  • 对于关键 Target(如 Kubelet、etcd),建议设置 scrape_retries: 1 以容忍瞬态网络抖动。
  • 避免设置过大的重试次数(如 >3),否则会加剧 Target 端负载并延迟后续抓取。
  • 重试次数过多时,可通过 prometheus_target_scrapes_exceeded_sample_limit_total 等指标监控抓取质量。

4.5 抓取生命周期相关指标

Prometheus 自身暴露了丰富的指标用于监控抓取过程,以下是核心指标:

指标名称 类型 说明
prometheus_target_scrapes_total Counter 抓取总次数,按 scrape_job、instance 标签区分
prometheus_target_scrapes_failed_total Counter 抓取失败次数(包括超时、HTTP 错误、解析错误)
prometheus_target_scrapes_timeout_total Counter 抓取超时次数
prometheus_target_scrapes_exceeded_sample_limit_total Counter 超过样本数限制的次数
prometheus_target_scrape_duration_seconds Gauge 最近一次抓取的耗时(秒)
prometheus_target_scrape_pool_sync_total Counter 抓取池同步次数,反映服务发现更新频率

4.6 常见故障排查清单

当 Target 抓取出现异常时,可按以下步骤排查:

  1. 检查 Target 状态页:Prometheus Web UI 的 /targets 页面会显示每个 Target 的状态(UP/DOWN)和上次错误信息。
  2. 查看 Prometheus 日志:使用 --log.level=debug 启动可获取详细的抓取日志。
  3. 验证网络连通性:从 Prometheus 节点直接 curl 目标 URL,确认是否可达。
  4. 检查超时配置:确认 scrape_timeout 是否过小,特别是对于返回大量指标的 Target。
  5. 检查样本数限制:查看 prometheus_target_scrapes_exceeded_sample_limit_total 是否增长,必要时调整 sample_limit。
  6. 检查 TLS 配置:HTTPS 模式下确认证书是否有效、是否过期、是否被正确信任。
  7. 检查重试配置:确认 scrape_retries 是否合理,避免因重试导致抓取间隔被压缩。

快速诊断命令示例:

# 从 Prometheus 节点手动测试抓取
curl -v --connect-timeout 5 --max-time 10 http://target-ip:8080/metrics

# 检查 Prometheus 自身抓取指标
curl -s http://localhost:9090/metrics | grep -E "prometheus_target_scrapes_(total|failed|timeout)"

# 查看特定 job 的抓取耗时分布
curl -s http://localhost:9090/api/v1/query?query=prometheus_target_scrape_duration_seconds{job="kubernetes-nodes"}