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 方法拉取最新目标组。
- 调用 NewDiscovery 方法,创建 Discovery 对象,内部会:
-
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 等都支持自定义。

浙公网安备 33010602011771号