prometheus 服务发现原理

2023-11-03

服务发现

概述

2b54bd1d5d70760ac9c0a01691630916.png

如上图,Prometheus核心功能包括服务发现、数据采集和数据存储。服务发现模块专门负责发现需要监控的目标采集点(target)信息,数据采集模块从服务发现模块订阅该信息,获取到target信息后,其中就包含协议(scheme)、主机地址:端口(instance)、请求路径(metrics_path)、请求参数(params)等;然后数据采集模块就可以基于这些信息构建出一个完整的Http Request请求,定时通过pull http协议不断的去目标采集点(target)拉取监控样本数据(sample);最后,将采集到监控样本数据交由TSDB模块进行数据存储。

为什么需要服务发现模块?

类似于微服务通过引入注册中心组件解决众多微服务间错综复杂的依赖调用。无论是服务主动停止,意外挂掉,还是因为流量增加对服务实现进行扩容,这些服务数据或状态上的动态变化,通过注册中心屏蔽服务状态变更造成的影响,简化了调用方处理逻辑。

同理,Prometheus最开始设计是一个面向云原生应用程序的,云原生、容器场景下按需的资源使用方式对于监控系统而言就意味着没有了一个固定的监控目标,所有的监控对象(基础设施、应用、服务)都在动态的变化。Prometheus解决方案就是引入一个中间的代理人,这个代理人掌握着当前所有监控目标的访问信息,Prometheus只需要向这个代理人询问有哪些监控目标即可,这种模式被称为服务发现(service discovery)。

目前,Prometheus支持的服务发现协议是非常丰富的,最新版本(2.41)已支持接近三十种服务发现协议:

<azure_sd_config>
<consul_sd_config>
<digitalocean_sd_config>
<docker_sd_config>
<dockerswarm_sd_config>
<dns_sd_config>
<ec2_sd_config>
<openstack_sd_config>
<ovhcloud_sd_config>
<puppetdb_sd_config>
<file_sd_config>
<gce_sd_config>
<hetzner_sd_config>
<http_sd_config>
<ionos_sd_config>
<kubernetes_sd_config>
<kuma_sd_config>
<lightsail_sd_config>
<linode_sd_config>
<marathon_sd_config>
<nerve_sd_config>
<nomad_sd_config>
<serverset_sd_config>
<triton_sd_config>
<eureka_sd_config>
<scaleway_sd_config>
<uyuni_sd_config>
<vultr_sd_config>
<static_config>

服务发现配置解析

1、Prometheus服务启动加载prometheus.yml配置文件会被解析Config结构体:

9ca6e1a1179c7c2c4da4054cfa07540c.png

Config结构体是配置类的最顶层结构,内部包含6个字段分别对应prometheus配置的6大组成部分。

2、其中数据采集配置部分ScrapeConfigs对应的是一个*ScrapeConfig类型切片,一个ScrapeConfig对应的是scrape_configs配置下的一个job抓取任务,服务发现协议配置对应其中ServiceDiscoveryConfigs字段:

50a3d50a35554fad00708cf4f7d76e52.png

3、discovery.Configs对应的是Config切片:

type Configs []Config

所以,一个job抓取任务下可以配置多个服务发现协议,如:

- job_name: 'prometheus'
  metrics_path: /metrics
  static_configs:
    - targets: ['124.222.45.207:9090']
  file_sd_configs:
    - files:
      - targets/t1.json
      - targets/t2.json
      refresh_interval: 5m

4、Config是一个接口:

3555cfd4e31986f95909d8fd0156aa1e.png

Config是一个接口的定义,每种服务发现协议都会存在一个对应Config接口的实现(见下图)。该接口主要定义两个方法:

1、Name() string:定义服务发现协议类型,如eureka、kubernetes等等;
2、NewDiscoverer(DiscovererOptions) (Discoverer, error):返回一个Discoverer类型变量,该类型也是一个接口,其只定义了一个方法Run方法,即Discoverer是对应的服务发现协议具体运行逻辑封装,通过Run方法提供统一的运行入口。

5fc510b4390a5cc4d03c75452acb809f.png

服务发现核心原理

40a88e60f17a6bb0b6ca106748856aab.png

说明:

  1. Prometheus服务发现核心逻辑的入口主要关注Manager结构体的ApplyConfig方法:基于服务发现的配置使其生效;

  2. ApplyConfig方法包括四个主要步骤:

    type provider struct {
     name   string
     d      Discoverer
     subs   []string
     config interface{}
    }

    一个job下一个服务发现协议对应一个Discoverer。

    provider还有额外三个字段:

    1、nameprovider名称,格式:fmt.Sprintf("%s/%d", typ, len(m.providers))

    2、subsstring切片,存放job名称,因为可能不同job下存在一致的服务发现配置,就只会生成一个provider,然后subs存放job列表;

    3、config:服务发现配置

    1. 启动Discoverer接口Run方法,让服务发现逻辑运行;

    2. 协程中运行updater方法;

    3. Discoverer接口Run方法主要基于具体服务发现协议发现target,然后通过通道传递给updater处理逻辑,将其解析处理放入到Manager结构体中targets字段中,并向triggerSend通道发送信号,表示当前targets发生变更;

    4. Manager结构体sender方法每5秒监听triggerSend通道信号,并将Manager结构体中targets字段处理后放入到syncCh通道中;

    5. 数据采集模块(scrape)监听syncCh通道,就可以获取到服务发现生成的targets信息,然后reloadtarget纳入监控开始抓取监控指标。

    6. 启动provider:遍历Manager结构体中providers切片,启动每个provider,该步骤主要是启动两个协程:

      Manager结构体sender方法是在Prometheus启动时discoveryManagerScrape.Run()方法中启动。

    7. 取消服务发现:配置变更也会调用ApplyConfig方法,这时就要把基于之前配置运行的服务发现服务取消,然后基于当前配置重新生成;

    8. 清空:主要清空discoverCanceltargetsproviders几个容器元素,因为要基于当前配置重新生成;

    9. 注册providerprovider是对Discoverer的封装,不同服务发现协议都会实现Config接口,其中NewDiscoverer方法就是创建Discoverer

「Prometheus服务发现核心就是三个协程之间协作:」

  1. 「协程1:」负责运行Discoverer接口Run方法,基于协议发现采集点;

  2. 「协程2:」负责将协程1发现的采集点信息更新到Manager结构体中targets字段的map中;

  3. 「协程3:」负责将Manager结构体中targets字段的数据通过通道发送给scrape模块;

scrape模块获取到采集点如何进行数据采集后续scrape模块分析。

监控指标

Prometheus服务发现通用指标主要有如下5个,都定义在discovery/manager.go中:

prometheus_sd_discovered_targets
prometheus_sd_failed_configs
prometheus_sd_received_updates_total
prometheus_sd_updates_delayed_total
prometheus_sd_updates_total

「1、采集点数量指标」

服务发现主要基于协议发现采集目标,prometheus_sd_discovered_targets指标反馈各个job发现的采集目标数:

prometheus_sd_discovered_targets:gauge类型,当前发现的目标数
config:job名称
name:取值scrape和notify,区分指标抓取服务发现还是告警通知服务发现
示例:prometheus_sd_discovered_targets{config="auth_es1", name="scrape"}  12

这里基于协议发现的目标数,还未进入采集模块,并不能区分是在线还是离线。

「2、服务发现协议异常错误指标」

服务发现会给每个发现配置项生成一个provider,并为每个provider使用协程运行,如果基于配置项生成provider错误就可以通过prometheus_sd_failed_configs指标反馈:

prometheus_sd_failed_configs:gauge类型,当前无法加载的服务发现配置数
配置数:一个job可能存在多个服务发现协议配置,对应配置项则是多个
示例:
prometheus_sd_failed_configs{name="scrape"}  10
prometheus_sd_failed_configs{name="notify"} 5

一个job可能对应多个服务发现配置项,如下:这个job下配置了static_configsfile_sd_configs两个服务发现协议配置,则对应两个服务发现配置项,注册两个provider,每个provider在独立协程中运行:

scrape_configs:
  # The job name is added as a label `job=` to any timeseries scraped from this config.
  - job_name: 'test'
    static_configs:
    - targets: ['localhost:9090']
    file_sd_configs:
    - refresh_interval: 5m
      files:
      - targets/manual.*.json

「3、协程交互指标」

服务发现主要涉及3类协程:

  1. Discoverer协程(多个):封装provider,基于协议发现采集点,这里可能会存在多个,一个provider对应一个Discoverer协程

  2. updater协程(1个):Discoverer协程发现采集点,通过channel通道通知到updater协程updater协程将采集点更新到Manager结构体targets字段中,然后向Manager结构体triggerSend通道写入数据,告诉sender协程targets有更新;

  3. sender协程(1个):sender协程每5秒检测triggerSend通道数据,检测到更新则将Manager结构体targets数据处理封装写入到Manager结构体syncCh通道中,scrape模块监测该通道,即完成将服务发现模块scrape模块交互。

这其中涉及三个指标:

prometheus_sd_received_updates_total
prometheus_sd_updates_delayed_total
prometheus_sd_updates_total

f8b0d231142e4dbee60b31347387dd58.png

bb3e0e6ab46e8f0abe6efe6bc4f3fd0d.gif

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

prometheus 服务发现原理 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • Gradle 复制文件 无知的菜墩

    Gradle 复制文件 很多大佬都是直接贴出如下代码 简单说就是 task 直接使用 from into include 等方法 然而直接复制下来之后 过了俩小时零一秒钟后依然无法使用 一直不生效 task nestedSpecs type
  • Go Facade外观(门面)设计模式

    动机 Motivation 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合 随着外部客户程序和各子系统的演化 这种过多的耦合面临很多变化的挑战 如何简化外部客户程序和系统间的交互接口 如何将外部客户程序的演化和内部子系
  • hbuilderx自定义常用代码块

    apipost body let res await this http post 1 if res code 200 2 else this toast res msg prefix apipost project uni app sco
  • hdu 5831 Rikka with Parenthesis II 2016 Multi-University 8

    Problem acm hdu edu cn showproblem php pid 5831 题意 给个括号序列 问能不能通过一次把两个不同位置的符号交换的操作 使得序列里的所有括号左右配对合法 分析 左括号进栈 如果是右括号而且栈顶是左
  • Linux性能监控命令_sar & 自动保存30天历史信息

    简介 sar命令将操作系统中选定的累积活动计数器的内容写入标准输出 计费系统根据 count 和 interval参数中的值 以秒为单位 按照指定的时间间隔写入指定次数的信息 目录 1 语法 1 1 常用参数 2 常见用法 2 1 监控CP
  • HTTP->WebRTC演进路径

    first HTTP Pre AJAX 原始web 一页里发送请求后才返回另一页 如Geocities second AJAX 2004 更新页面不需要刷新 如GMail third Web Sockets 2008 页面能建立双向通信 通
  • Android 10 暗黑模式适配,你需要知道的一切

    在 Android 10 里 Dark theme 暗黑模式得到了系统级的支持 暗黑模式不仅酷炫 而且有降低屏幕耗电 在光线较暗的环境中使用更舒适等好处 今天带大家看一下如何适配暗黑模式 本文会从以下几点进行介绍 动态开启暗黑模式 使用 D
  • 解密IP地址的不同潜力与应用场景

    作为专业爬虫代理供应商 我们经常需要面对不同的IP地址需求 在IP地址选择中 动态IP和静态IP是两个常见的选项 但究竟什么是动态IP和静态IP 它们有什么区别和优势 适用于哪些场景 本文将为你详细解答 让你对IP地址有更全面的了解 第一部
  • html文字图片同一行,CSS控制图片和文字在同一行显示且对齐的3种方法

    CSS控制图片和文字在同一行显示且对齐的3种方法 在 HTML 代码中 有时会需要在文字旁边加上一个图标 默认情况 是图片置顶对齐 文字置底对齐 所以通常图片高 文字低 不能水平居中对齐 常见欢思中属餐显近和想都性厅示近和想都性厅示方法有3
  • Java并发JUC集合类

    文章目录 Java并发JUC集合类 为什么HashTable慢 它的并发度是什么 ConcurrentHashMap在JDK1 7和JDK1 8中实现有什么差别 JDK1 8解決了JDK1 7中什么问题 ConcurrentHashMap
  • Java jinfo 命令详解

    jinfo 命令可以用来查看 Java 进程运行的 JVM 参数 命令如下 root admin jinfo help Usage jinfo option
  • 40 多名直接下属、从不 1 对 1 沟通,老黄如此管理下的英伟达能在 AI 芯片领域称霸多久?...

    省时查报告 专业 及时 全面的行研报告库 省时查方案 专业 及时 全面的营销策划方案库 免费下载 2023年8月份全网热门报告合集 ChatGPT提词示例 让你的ChatGPT聪明100倍 超百页干货资料 AI应用的难点 痛点与未来 202
  • It's Not Just Standing Up: Patterns of Daily Stand-up Meetings

    It s Not Just Standing Up Patterns of Daily Stand up Meetings Jason Yip ThoughtWorks Inc jcyip thoughtworks com http mar
  • VScode launch.json和tasks.json文件的配置

    task json version 2 0 0 command g args g file o file exe 编译命令参数 problemMatcher owner cpp fileLocation relative workspace
  • 高效的学习方法(费曼学习方法)

    学习技巧有四个简单的步骤 1 提取书本信息 阅读并理解 拿出一张白纸简要概括知识点以及对知识点进行深度拓展和横向拓展 深度拓展指增强知识点的理解深度 可以通过提问题的方式加强深度理解 横向拓展指增强其阅读广度 通过与其他学科建立关联 2 在
  • #pragma once和#ifndef / #define / #endif的区别

    转摘自 http www 360doc com content 10 0124 00 722458 14261695 shtml pragma once 指令格式如下 pragma once这是一个比较常用的指令 只要在头文件的最开始加入这
  • 华为OD机试 - 跳房子II(Java)

    题目描述 跳房子 也叫跳飞机 是一种世界性的儿童游戏 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格 然后获得一次选房子的机会 直到所有房子被选完 房子最多的人获胜 跳房子的过程中 如果有踩线等违规行为 会结束当前回合 甚至可能
  • c++什么时候使用new,调用构造函数

    new 补充 构造函数的调用 对象 可以调用成员函数 不可以调用构造函数 我们无法像调用成员函数那样使用对象来调用构造函数 因为在构造函数构造出对象之前 对象是不存在的 因此构造函数被用来创建对象 而不能通过对象来调用 详见 构造函数的4种
  • 三台机器搭建redis集群过程及问题记录

    文章目录 1 前言 2 搭建集群 3 遇到的问题 4 相关文章 1 前言 Redis版本 5 0 4 服务器版本 Linux CentOS 6 CentOS 7 CentOS 9 redis集群需要至少要三个master节点 我们这里搭建三
  • prometheus 服务发现原理

    服务发现 概述 如上图 Prometheus核心功能包括服务发现 数据采集和数据存储 服务发现模块专门负责发现需要监控的目标采集点 target 信息 数据采集模块从服务发现模块订阅该信息 获取到target信息后 其中就包含协议 sche