【prometheus】-02 一张图彻底搞懂Prometheus服务发现机制

概述

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

如上图,SD模块专门负责去发现需要监控的target信息,Prometheus去从SD模块订阅该信息,有target信息时会推送给Prometheus,然后Prometheus拿到target信息后通过pull http协议去拉取监控指标数据。

Prometheus支持的服务发现协议是非常丰富的,目前已支持多达二十多种服务发现协议:


【资料图】

服务发现原理图

上图描述Prometheus服务发现协议比较笼统,Prometheus服务发现实现原理大致如下图:

如上图所述,Prometheus服务发现机制大致涉及到三个部分:

1、配置处理模块解析的prometheus.yml配置中scrape_configs部分,将配置的job生成一个个Discoverer服务,不同的服务发现协议都会有各自的Discoverer实现方式,它们根据实现逻辑去发现target,并将其放入到targets容器中;

2、discoveryManager组件内部有个定时周期触发任务,每5秒检查targets容器,如果有变更则将targets容器中target信息放入到syncCh通道中;

3、scrape组件会监听syncCh通道,这样需要监控的targets信息就传递给scrape组件,然后reloadtarget纳入监控开始抓取监控指标。

配置处理部分会根据scrape_configs部分配置的不同协议类型生成不同Discoverer,然后根据它们内部不同的实现逻辑去发现targetdiscoveryManager组件则相当于一个搬运工,scrape组件则是一个使用者,这两个组件都无感知服务发现协议的差异。

下面分别来分析下配置处理、discoveryManager组件和scrape组件在服务发现方面的具体实现流程。

配置处理

上节分析Prometheus启动流程,有个配置加载组件通过reloadConfig加载解析prometheus配置文件后,在reloader中循环调用各个组件的ApplyConfig(cfg map[string]Configs)方法处理配置,这其中就包括discovery/manager.go:

reloader中定义如下:

{name:"scrape_sd",//从配置文件中提取Section:scrape_configsreloader:func(cfg*config.Config)error{c:=make(map[string]discovery.Configs)for_,v:=rangecfg.ScrapeConfigs{c[v.JobName]=v.ServiceDiscoveryConfigs}returndiscoveryManagerScrape.ApplyConfig(c)},}

那下面就从discovery/manager.go中定义的ApplyConfig()方法分析。

1、根据配置注册provider:

forname,scfg:=rangecfg{//根据配置注册providerfailedCount+=m.registerProviders(scfg,name)discoveredTargets.WithLabelValues(m.name,name).Set()}

其中关键的是m.registerProviders(scfg, name),继续跟踪:

d,err:=cfg.NewDiscoverer(DiscovererOptions{Logger:log.With(m.logger,"discovery",typ),})

2、然后将所有注册到m.providers数组中的provider进行启动:

for_,prov:=rangem.providers{//启动服务发现实例m.startProvider(m.ctx,prov)}

跟踪到m.startProvider(m.ctx, prov)方法中:

updates:=make(chan[]*targetgroup.Group)//执行run 每个服务发现都有自己的run方法。gop.d.Run(ctx,updates)//更新发现的服务gom.updater(ctx,p,updates)

发现这里主要是启动两个协程,它们之间使用updates通道类型变量进行通信。

总结来说(见下图):

1、每个Config都会对应创建一个Discoverer实例,并被封装到provider存储在m.providers数组中;

2、然后遍历providers数组进行启动操作,启动操作启动了两个协程:

a、Discoverer.Run协程逻辑中主要根据发现协议发现targets

b、然后通过通道传递给discovery/Manager.updater协程中,将其存放到m.targets集合map中;

配置处理这里还有个比较关键的:Discoverer会根据不同协议实现发现target,它是如何实现的呢?

首先,我们来看下Discoverer实例创建:d, err := cfg.NewDiscoverer(),它是一个接口定义:

typeConfiginterface{Name()stringNewDiscoverer(DiscovererOptions)(Discoverer,error)}

每种服务发现协议都在自己的SDConfig中实现了各自的NewDiscoverver()方法,这样就可以将服务发现逻辑封装到Discovererver实现中:

discoveryManager组件

上节《Prometheus启动流程》一节分析过会启动discoveryManagerScrape组件通过通道将targets数据信息传递给scrapeManager组件(见下图):

1、discoveryManagerScrape组件启动入口:

g.Add(func()error{err:=discoveryManagerScrape.Run()level.Info(logger).Log("msg","Scrapediscoverymanagerstopped")returnerr},func(errerror){level.Info(logger).Log("msg","Stoppingscrapediscoverymanager...")cancelScrape()},)

2、一直跟踪会进入到sender()方法中,配置处理模块说过,有个协程会将Discoverer组件发现的targets信息存储到m.targets集合map中,然后给m.triggerSend发送信号,sender方法中就是启动定时周期触发器监听m.triggerSend信号:

func(m*Manager)sender(){//周期性定时器定时触发任务,这里是5s触发一次ticker:=time.NewTicker(m.updatert)deferticker.Stop()for{select{case<-m.ctx.Done():returncase<-ticker.C://Somediscovererssendupdatestoooftensowethrottlethesewiththeticker.select{case<-m.triggerSend:sentUpdates.WithLabelValues(m.name).Inc()select{casem.syncCh<-m.allGroups():default:delayedUpdates.WithLabelValues(m.name).Inc()level.Debug(m.logger).Log("msg","Discoveryreceiver"schannelwasfullsowillretrythenextcycle")select{casem.triggerSend<-struct{}{}:default:}}default:}}}}

监听到m.triggerSend信号,则执行m.syncCh <- m.allGroups(),我们来看下m.allGroups()干了什么?

func(m*Manager)allGroups()map[string][]*targetgroup.Group{m.mtx.RLock()deferm.mtx.RUnlock()tSets:=map[string][]*targetgroup.Group{}forpkey,tsets:=rangem.targets{varnintfor_,tg:=rangetsets{//Evenifthetargetgroup"tg"isemptywestillneedtosendittothe"Scrapemanager"//tosignalthatitneedstostopallscrapeloopsforthistargetset.tSets[pkey.setName]=append(tSets[pkey.setName],tg)n+=len(tg.Targets)}discoveredTargets.WithLabelValues(m.name,pkey.setName).Set(float64(n))}returntSets}

其实就是将m.targets数据发送到m.syncCh通道上,所以,discoveryManager组件比较简单,就是一个搬运工。

scrape组件

scrapeManager组件启动:scrapeManager.Run(discoveryManagerScrape.SyncCh()),通道syncCh是被scrapeManager组件持有的,跟踪进入Run方法中:

func(m*Manager)Run(tsets<-chanmap[string][]*targetgroup.Group)error{gom.reloader()for{select{//通过管道获取被监控的服务(targets)casets:=<-tsets:m.updateTsets(ts)select{//关闭ScrapeManager处理信号//若从服务发现(serviceDiscover)有服务(targets)变动,则给管道triggerReload传值,并触发reloader()方法更新服务casem.triggerReload<-struct{}{}:default:}case<-m.graceShut:returnnil}}}

通过case ts := <-tsets获取到syncCh通道上传递过来的targets数据,然后调用m.updateTsets(ts)targets数据存储到scrapeManager.targetSets中,然后给m.triggerReload发送信号。

这个方法中go m.reloader()启动了一个协程,进入reloader()方法中:

func(m*Manager)reloader(){//定时器5sticker:=time.NewTicker(*time.Second)deferticker.Stop()for{select{case<-m.graceShut:return//若服务发现(serviceDiscovery)有服务(targets)变动,就会向管道triggerReload写入值,定时器每5s判断一次triggerReload管道是否有值,若有值,则触发reload方法case<-ticker.C:select{case<-m.triggerReload:m.reload()case<-m.graceShut:return}}}}

也是通过定时周期触发任务监听m.triggerReload信号,执行m.reload()targets加载进来。

总结

前面分析了服务发现运行机制,可以看下面图梳理下前面流程逻辑:

标签:

最近更新

【prometheus】-02 一张图彻底搞懂Prometheus服务发现机制
2023-03-24 22:20:30
快讯:快讯|光大银行:2022年实现归母净利润448.07亿元,同比增长3.23%
2023-03-24 20:56:21
90后小伙遭遇漆树“咬人” 浑身红肿险些误诊
2023-03-24 19:08:04
丽江到泸沽湖要多久路好走吗|全球关注
2023-03-24 17:30:31
报告:2022年四季度申请进网检测手机94款,5G占近六成
2023-03-24 17:47:45
下课消息传出后,纳格尔斯曼“空降”热刺新帅赔率第一
2023-03-24 15:59:31
网络诈骗盯上个税退税,如何避险鉴别信息真伪?
2023-03-24 15:18:18
和讯个股快报:2023年03月24日 梦网科技(002123)13:19分,股价快速拉升 当前视点
2023-03-24 13:21:59
亿道信息:公司产品可支持大多数工业制造行业
2023-03-24 11:59:26
天天热资讯!还有油吗?媒体人:归化球员“小摩托”费南多将返回中国踢球
2023-03-24 11:04:55
迈克乔丹的有关资料
2023-03-24 09:52:46
全球百事通!开怀大笑!樊振东夺冠后的庆祝太暴力了!有点不尊重马龙!
2023-03-24 10:02:38
【外盘异动】相较于隔夜23:00 美原油(23:00基准)下跌2.97%
2023-03-24 08:37:22
每日热议!钟罩阀规格型号(钟罩阀)
2023-03-24 06:24:59
当前快看:sail是什么意思中文翻译_sail是什么意思
2023-03-24 02:03:49
古代灌铅是什么刑法?_灌铅是什么刑-环球热点
2023-03-23 22:41:14
全球今日讯!离婚证样本是什么样的
2023-03-23 20:53:11
南充将军大桥何时开通公交线?
2023-03-23 20:56:03
2月厦门存款余额超1.7万亿元_世界速看料
2023-03-23 19:17:59
山石网科(688030.SH):2名股东拟合计减持不超111.66万股-全球观热点
2023-03-23 17:56:36
凯发电气:公司坚持“致力于轨道交通领域,以优质的服务、领先的技术成为行业细分领域的引领者”的发展战略
2023-03-23 16:15:24
雄安容城县关于影院路和侯庄北街施工断交导行的通告
2023-03-23 15:02:48
神州信息五项解决方案入选“2022年度金融信创优秀解决方案” 头条焦点
2023-03-23 14:31:31
全球讯息:箱子尺寸规格表
2023-03-23 13:50:44
天天信息:IMAX发布《燃烧的巴黎圣母院》专属海报,法国著名导演让-雅克·阿诺执导
2023-03-23 12:26:43
首都机场临空经济区——建设朝阳产业聚集地
2023-03-23 11:09:23
当前最新:和讯个股快报:2023年03月23日 浪潮信息(000977)该股换手率大于8%
2023-03-23 09:57:09
【春日里的中国】百鸟戏春!首批东方白鹳飞抵这里
2023-03-23 08:13:26
宋朝柴王背景|当前观察
2023-03-23 06:07:58
畏寒最有可能是得了什么病_畏寒有哪些症状
2023-03-23 04:58:30