Prometheus源码专题【左扬精讲】—— 监控系统 Prometheus 3.4.0 源码解析:Discovery 动态服务发现机制——discovery/http/http.go

Prometheus源码专题【左扬精讲】—— 监控系统 Prometheus 3.4.0 源码解析:Discovery 动态服务发现机制——discovery/http/http.go

        Prometheus 作为业界主流的监控与告警系统,具备多种灵活的服务发现(Service Discovery)方式,其中 HTTP 服务发现(http_sd)尤为突出,它凭借极高的灵活性与强大的扩展性脱颖而出。该机制通过简洁的 HTTP/HTTPS 接口,支持以任意方式动态维护监控目标,尤其适用于应对复杂多变的微服务架构或自研系统场景。

        本文将结合 Prometheus 源码中的 discovery/http/http.go 文件,深入剖析 http_sd 的使用方法及其内部实现原理,帮助读者不仅更好地掌握其接入与问题排查技巧,还能为自定义开发更贴合业务需求的服务发现插件提供参考。

一、如何通过 http.go 方式接入 Prometheus 服务发现

1.1 什么是 HTTP 服务发现?

       HTTP 服务发现允许你通过一个自定义的 HTTP/HTTPS 接口,动态地向 Prometheus 提供监控目标(target groups)。这对于那些自建自动化平台、或内部有特殊服务编排逻辑的公司非常实用。你只需要实现一个接口,返回 Prometheus 约定格式的 JSON,Prometheus 就能自动采集到你的监控目标。

1.2 配置方法

在 Prometheus 的配置文件 prometheus.yml 中加入如下 job 配置:

scrape_configs:
  - job_name: 'custom-http-sd'
    http_sd_configs:
      - url: 'http://your-service-discovery-endpoint/api/prometheus/targets'
        refresh_interval: 30s
    relabel_configs:
      # 按需 relabel

参数说明:

  • url:自定义 HTTP 服务发现 Endpoint,Prometheus 会定期 GET 这个 URL。
  • refresh_interval:Prometheus 拉取 Endpoint 的频率,默认 60s,可自定义。
  • 该 Endpoint 需要返回如下结构的 JSON 响应(target group 列表):
    [
      {
        "targets": ["10.0.0.1:9100", "10.0.0.2:9100"],
        "labels": { "env": "production" }
      }
    ]

1.3 HTTP SD 适用场景

    • 你的目标服务动态变化,不能通过静态配置、DNS、Kubernetes 等标准方式发现。
    • 有一套自己的服务编排/注册中心,但 Prometheus 不直接支持。
    • 想将服务发现逻辑与 Prometheus 解耦,灵活扩展。

二、discovery/http/http.go 源码详解

接下来,我们详细解读下 http.go 的核心实现逻辑。

2.1、核心结构体(SDConfig)

定义 HTTP 服务发现的配置项,包括 HTTP 客户端配置、刷新间隔、目标 URL。

type SDConfig struct {
    HTTPClientConfig config.HTTPClientConfig // HTTP 客户端相关配置
    RefreshInterval  model.Duration          // 刷新间隔
    URL              string                  // 服务发现 endpoint
}

2.2、核心结构体(Discovery)

代表一次 HTTP 服务发现任务,管理目标 URL、HTTP 客户端、定时刷新等。

type Discovery struct {
    *refresh.Discovery                // 嵌入定时刷新机制
    url             string            // 目标 URL
    client          *http.Client      // HTTP 客户端
    refreshInterval time.Duration     // 刷新间隔
    tgLastLength    int               // 上一次目标组数量
    metrics         *httpMetrics      // 指标采集
}

2.3、核心流程

1. 配置初始化

      • 通过 SDConfig 进行反序列化(UnmarshalYAML),自动完成参数校验:URL 必须有效、协议为 http/https、Host 不为空等。

2. 注册服务发现机制

      • 在包初始化时调用 discovery.RegisterConfig(&SDConfig{}),将 HTTP SD 注册到 Prometheus 的发现体系。

3. 创建 Discovery 实例

      • 调用 NewDiscovery 方法,创建 Discovery 对象,内部会:
        • 初始化 HTTP 客户端,设置超时时间。
        • 结合 refresh 机制定时调用 Refresh 方法拉取最新目标组。

4. 拉取目标组数据(Refresh 方法)

      • 构造 HTTP GET 请求,加上必需的 User-Agent、Accept 头,以及自定义刷新间隔头。
      • 发起请求,检查 HTTP 状态码和 Content-Type,确保为 200 OK 且返回 JSON。
      • 解析响应体为目标组列表([]*targetgroup.Group)。
      • 为每个 group 增加 __meta_http_sd_url 标签(方便后续 relabel/去重)。
      • 如果目标组数量减少,会补齐空 group,保证 Prometheus 能感知目标组的下线。

5. 目标组结构

      • 每个目标组需要包含 targets 字段(监控地址数组),labels 字段(key-value 标签对),以及 source 字段(唯一标识来源)。

2.4 源码亮点

    • 健壮性:请求失败、响应格式校验失败、反序列化失败都会增加失败指标,便于监控和排查。
    • 自动补齐空目标组:防止目标组下线后,Prometheus 无法感知的问题。
    • 标签自动注入:支持自动为每个目标组加上来源 URL,方便追踪来源。
    • 可配置性高:HTTP 客户端参数、TLS、认证、Header 等都支持自定义。
posted @ 2025-08-08 14:35  左扬  阅读(27)  评论(0)    收藏  举报