夜莺和prometheus告警流程比照剖析
prometheus告警流程剖析
以 sum(rate(coredns_dns_requests_total[1m])) > 100 为例
- alert和record复用大部分逻辑
- prometheus依据配置文件中拿到规定
- 解析规定查问本地存储或远端存储(带触发条件),trigger在存储端
- 返回一组以后点后果集,返回多少个对应多少条告警
- 依据内存中的历史数据判断告警持续时间(for 1 min)有没有达到
- 发送告警event给alertmanager
- 由alertmanager做告警的发送、静默、分组路由、关联、回调
夜莺告警流程剖析
- monapi 定时从db同步策略,judge 依据本人的ident 拿到属于本人的策略
- transfer依据存活的judge 拿到所有策略,将策略的judge地址填好
transfer收到 agent push的数据后,算hash拿到策略列表
- 依据策略拿到judge地址,依据缓存拿到对应的队列,将数据塞入队列中
- judge收到策略后,依据策略中的fun做触发
- 依据策略中配置实现 发送工夫、告警降级、回调等
两边本质区别
零碎 | 阈值判断 | 是否反对多series告警 | 触发条件 | 组合条件 | nodata |
---|---|---|---|---|---|
夜莺v4 push代表 | 由judge接收点触发判断,查问本地数据 | 不反对,每个策略针对繁多series 对应judge中内存列表 只能用预聚合解决 | 将happen、all、any等和聚合 avg max min等揉在一起 | 需做pull | 需做pull |
prometheus pull代表 | 由promql 查问存储 | promql间接反对 查问到一个就是一条,多个就是多条 | prometheus触发条件只反对 持续时间,其余的全副为聚合func | promql and反对 | promql absent反对 |
告警push模式的性能晋升问题
总结就是相比于性能损耗pull模型带来的灵活性是微小的
- push型的告警模式无疑会带来性能晋升
- 因为pull模型须要每次查问存储,尽管是以后点,但也有些损耗
然而
- 古代的tsdb 有倒排索引+布隆过滤器的加持,告警查问损耗能够降到很低- pull模型带来的是非常灵活的触发表达式,从这点看,性能损耗能够疏忽不急- 而且当初告警触发时都须要带上一些聚合的办法,这点push模型做不到
告警push模式能够工作在查问存储挂掉的case
因为push本地内存中有响应的数据,然而我感觉这是个伪劣势
在夜莺中引入pull的问题
- 最大的能源是否是相中了promql
- 存储和采集不反对promql
- 触发和聚合混在一起
代码剖析
夜莺v4代码问题
- 策略太多双层map reinit 耗时长
- 全局变量满天飞
syncStras
全副更新,耗时长,db read高- 每个judge实例拿到的还是全局数据,而且没有抢锁设计,导致多个judge实例同时全表读db- 除非db那里做分片,分region
- judge push模型报警很难将 pull模式融入进来
prometheus告警代码剖析
- update 加载配置文件,增量更新告警/聚合 group
group.Eval 计算组里的规定
- `// Eval runs a single evaluation cycle in which all rules are evaluated sequentially.`- `vector, err := rule.Eval(ctx, ts, g.opts.QueryFunc, g.opts.ExternalURL)`- 返回的是vector `type Vector []Sample` 代表享有对立时刻的一堆point- rule.Eval 分为规定和聚合 `alert/record`- 调用 EngineQueryFunc ,外部调 instance_query - `// EngineQueryFunc returns a new query function that executes instant queries against// the given engine.`- 如果没取到数据,证实没达到触发条件则,只解决历史的alert,看看持续时间到了没- 如果rule是 alert则走发送逻辑` if ar, ok := rule.(*AlertingRule); ok {ar.sendAlerts(ctx, ts, g.opts.ResendDelay, g.interval, g.opts.NotifyFunc)}` - alert 存在headblock中,record 写入存储中?
夜莺v4 告警代码 剖析
judge 依据本人的ident 拿到属于本人的策略
stras := cache.StraCache.GetByNode(node)
- 更新本地`cache.NodataStra` 和 `cache.Strategy`
monapi 定时从db同步策略
syncStras
- 分设施相干or设施无关- 依据策略的id算哈希,生成`strasMap [judge_ip_port][]*stra`- 全量更新 `cache.StraCache`
transfer依据存活的judge 拿到所有策略
stras := cache.StraCache.GetAll()
,将策略的judge地址填好- 依据所有策略的metrics 算哈希- 哈希前两位作为 map的第一层key- 外部map key为 哈希值,value为 策略列表- `straMap := make(map[string]map[string][]*models.Stra)`- `cache.StraMap.ReInit(straMap)`
transfer收到 agent push的数据后,算hash拿到策略列表
- 遍历策略列表 匹配tag- 依据策略拿到judge地址,依据缓存拿到对应的队列,将数据塞入队列中
- judge rpc send中
go judge.ToJudge(cache.HistoryBigMap[pk[0:2]], pk, item, now)