夜莺监控v3组件分析---Redis
夜莺V3 redis组件使用
夜莺通过redis
应用推送告警,主要利用了其消息队列功能。v3版本redis
客户端采用redigo
,夜莺v3的告警架构图如下所示
redis
告警信息流程如下所示:
judge
模块直接从transfer
中取出指标与其从monapi
同步的告警策略匹配,生成的event
推送到redis
服务器,代码如下
一、开启redis
连接池
func Init(cfg RedisSection) {...//与monapi开启的连接池不同,这里每一个redis服务器地址匹配一个连接池for i := range addrs {addr := addrs[i]redisConnPool := &redis.Pool{MaxIdle: maxIdle,IdleTimeout: idleTimeout,Dial: func() (redis.Conn, error) {c, err := redis.Dial("tcp", addr, redis.DialConnectTimeout(connTimeout), redis.DialReadTimeout(readTimeout), redis.DialWriteTimeout(writeTimeout))...if db != 0 {if _, err := c.Do("SELECT", db); err != nil {c.Close()logger.Error("redis select db fail, db: ", db)stats.Counter.Set("redis.conn.failed", 1)return nil, err}}return c, err},TestOnBorrow: PingRedis,}//所有连接池组成一个连接池组RedisConnPools = append(RedisConnPools, redisConnPool)}}
二、告警指标匹配告警策略
judge
模块中judge包
中,Tojudge
方法结合策略及指标生成告警
func ToJudge(historyMap *cache.JudgeItemMap, key string, val *dataobj.JudgeItem, now int64) {//获取告警策略stra, exists := GetStra(val.Sid)...linkedList, exists := historyMap.Get(key)if exists {needJudge := linkedList.PushFrontAndMaintain(val, stra.AlertDur)if !needJudge {return}} else {NL := list.New()NL.PushFront(val)//链表存储历史告警数据linkedList = &cache.SafeLinkedList{L: NL}historyMap.Set(key, linkedList)}...if len(stra.Exprs) == 1 {for _, expr := range stra.Exprs {//Judge方法传入stra策略,expr指标,hitstoryData历史数据...history, info, lastValue, status := Judge(stra, expr, historyData, val, now)statusArr = append(statusArr, status)if value == "" {value = fmt.Sprintf("%s: %s", expr.Metric, lastValue)} else {value += fmt.Sprintf("; %s: %s", expr.Metric, lastValue)}historyArr = append(historyArr, history)eventInfo += info}} ...event := &dataobj.Event{ID: fmt.Sprintf("s_%d_%s", stra.Id, val.PrimaryKey()),Etime: now,Endpoint: val.Endpoint,CurNid: val.Nid,Info: eventInfo,Detail: string(bs),Value: value,Partition: redi.Config.Prefix + "/event/p" + strconv.Itoa(stra.Priority),Sid: stra.Id,Hashid: getHashId(stra.Id, val),}//将数据push到redis服务器中sendEventIfNeed(statusArr, event, stra)
}
最后sendEventIfNeed(statusArr, event, stra)
将事件推送到redis
服务器,其中统一调用sendEvent
方法push数据
func sendEvent(event *dataobj.Event) {// update last eventcache.LastEvents.Set(event.ID, event)//调用push方法推送eventerr := redi.Push(event)if err != nil {stats.Counter.Set("redis.push.failed", 1)logger.Errorf("push event:%v err:%v", event, err)}
}
push
方法如下
func Push(event *dataobj.Event) error {bytes, err := json.Marshal(event)...//调用连接池连接for i := range RedisConnPools {rc := RedisConnPools[i].Get()defer rc.Close()// 如果写入用lpush 则读出应该用 rpop// 如果写入用rpush 则读出应该用 lpopstats.Counter.Set("redis.push", 1)_, err = rc.Do("LPUSH", event.Partition, string(bytes))if err == nil {succ = truebreak}}...
}
至此,已完成告警推送的前半部工作:将告警事件推送到redis
服务器。接下来需要将告警事件从服务器队列中pop出来
三、从redis
服务器中pop告警事件
在monapi
模块redis
包中初始化redis,主要代码如下:
这里不同于Judge
模块需要建立多个redis
服务器地址的连接池,通过特定的addr
将告警信息pop出来
func InitRedis() {cfg := config.Get()addr := cfg.Redis.Addrpass := cfg.Redis.PassmaxIdle := cfg.Redis.IdleidleTimeout := 240 * time.Second//建立一个连接池RedisConnPool = &redis.Pool{MaxIdle: maxIdle,IdleTimeout: idleTimeout,//建立连接池,通过pool对象中Get()方法调用redis连接Dial: func() (redis.Conn, error) {c, err := redis.Dial("tcp", addr, redis.DialConnectTimeout(connTimeout), redis.DialReadTimeout(readTimeout), redis.DialWriteTimeout(writeTimeout))....return c, err},TestOnBorrow: PingRedis,}
}
那么告警是如何消费的?
在monapi
模块alarm
包中定义了event_reader
模块从redis
中获取告警事件,方法popEvent
的主要操作如下
func popEvent(queues []interface{}) (*models.Event, bool) {queues = append(queues, 1)//与redis服务器建立连接(通过pool)rc := redisc.RedisConnPool.Get()//最后一定要关闭,不然会报错defer rc.Close()//执行BRPOP操作,从list列表中弹出最后一个元素,如果没有将阻塞,阻塞时间可以设置,这里是默认值reply, err := redis.Strings(rc.Do("BRPOP", queues...))//异常处理if err != nil {...}if reply == nil {...}
popEvent
方法被func ReadHighEvent()
、func ReadLowEvent()
调用,通过consume
发明合法按需处理条件告警事件(包括调整、推送、存储、升级、屏蔽等)。
这里有一个问题:为社么从Jugde
push到redis
队列中是event
,为什么monapi
中是从YAML文件
中取出告警事件队列?
结合redis in action
里面对消息队列的说明,为了将告警事件push到队列里面,程序会获取告警所需的全部信息,并将这些信息转化为JSON
对象,最后使用RPUSH
或者LPUSH
将JSON对象推入到队列里,因为这种格式能够被人类读懂,而且大部分语言都提供了JSON
格式快速转码的函数库。
func ReadHighEvent() {//从Queue结构体中队queues := config.Get().Queue.High...//取出告警事件for {event, sleep := popEvent(queues)if sleep {time.Sleep(duration)continue}//按条件调整、推送、存储告警事件,具体见方法源代码consume(event, true)}
}
四、总结
夜莺使用redis
告警主要有两大模块,Judge
和monapi
,Judge
将指标与策略结合生成告警push到redis
队列,monapi
将队列中的事件pop出来做后续处理以及消息分发。
Judge
模块代码结构
backend
:创建连接池,初始化,封装push方法等cache
:缓存config
:redis配置文件http
:路由Judge
:结合指标及策略生成告警(关键)- ····
monapi
模块代码结构正在研究当中,上述接个人理解,欢迎大家批评指正
附录
redigo
参考文档:https://pkg.go.dev/github.com/gomodule/redigo/redis#pkg-variables
夜莺监控v3组件分析---Redis相关推荐
- 夜莺(Flashcat)V6监控(五):夜莺监控k8s组件(上)
目录 (一)Kubernetest监控体系 1.Kubernetes监控策略 (二)K8s-ApiServer组件监控 (1)我们先创建一个namespace来专门做夜莺监控采集指标 (2)创 ...
- 更换jdk版本_滴滴夜莺发布 v3 版本,从运维监控演化成了运维平台
Nightingale 从 3 月份开源到现在,过去了半年多点时间,收获了接近 2000 个 github star,300 多个 issue 升级说明 v3.x的版本和v2.x差别巨大,没办法平滑迁 ...
- 夜莺监控( Nightingale ),看这一篇就够了。(介绍、部署、配置、优化、自定义)
文章目录 夜莺监控( Nightingale ) 概述 技术选型 categraf 简介 产品对比 nightingale 简介 系统架构 产品对比 Prometheus 简介 特点 组件介绍 架构规 ...
- 01.夜莺监控简介及安装
夜莺监控系统介绍 夜莺监控( Nightingale )是一款国产.开源云原生监控分析系统,采用 All-In-One 的设计,集数据采集.可视化.监控告警.数据分析于一体.于 2020 年 3 月 ...
- 夜莺监控之Categraf监控VMwareVSphere
之前一直在使用开源的虚拟化软件PVE(Proxmox VE),突然有一天网桥莫名其妙的出幺蛾子,周末鼓捣了半天,谷歌百度也找不到对应的解决方案,重新安装烦的不行,后来一怒之下就换了VMware的VSp ...
- Nightingale滴滴夜莺监控系统入门(五)--采集功能
Nightingale滴滴夜莺监控系统入门(五)–采集功能 不知不觉夜莺已经更新到3.6版本,后续会议3.6来演示夜莺支持采集[端口][进程][日志][自定义插件]以及在3.5版本以后支持的主动采集[ ...
- redis缓存实现原理php,分析redis原理及实现
下面由Redis教程栏目给大家介绍分析redis原理及实现,希望对需要的朋友有所帮助! 1 什么是redis redis是nosql(也是个巨大的map) 单线程,但是可处理1秒10w的并发(数据都在 ...
- 性能测试监控指标和分析
一.软件性能测试需要监控哪些关键指标? 软件性能测试的目的主要有以下三点: 1.评价系统当前性能,判断系统是否满足预期的性能需求. 2.寻找软件系统可能存在的性能问题,定位性能瓶颈并解决问题. 3.判 ...
- 手把手教你搭建Nightingale夜莺监控系统
⚠:我依旧是那个不懂技术的小白! 俗话说:无监控不运维! 我身为一个运维界的小白!最常用的监控有:Zabbix,Prometheus,Nagios,CACTI ,夜莺,以及小米的开源监控open-fa ...
最新文章
- 55、组播配置实验之PIM Sparse Mode静态指定RP
- bitcask存储引擎
- BZOJ2653 middle 【主席树】【二分】*
- 设计模式-模板模式-个人理解
- 字节3-1前端面试官自学Vue的正确姿势
- [JavaWeb-JavaScript]JavaScript_Math数学对象
- 中国游戏公司研运一体发展专题分析2020
- Meta Company在公开信中谴责Facebook改名
- android驱动在win10系统上安装的心酸历程
- 写一个自己的javascript库
- 无线路由器与交换机配合使用,图解
- 薪资16K,进华为外包怎么样?
- vue中如何设置鼠标经过切换样式
- 程序员在跳槽时,该怎么说离职原因?
- html+css发光字体
- 冰刃(IceSword)的使用方法(高级篇)
- Html5 1.4 figure和figcaption的实例
- 二十二、商城 - 商品录入-FastDFS(10)
- 专访王威廉:NLP哪些研究方向更容易取得突破?
- 使用SPSS进行多元回归分析
热门文章
- 4g网络什么时候淘汰_5G时间表已出4G会被淘汰吗 4g网络还能用多久
- 2021年12月中国车企新能源汽车销量排行榜:Top前三的车企销量远超于其他车企,且市场份额占比均超过10%(附月榜TOP68详单)
- Transformer课程 第46章 Transformer模型TAPAS架构
- 管理批量邮箱 FOXMAIL 和网易闪电邮(PC端)有什么区别? 对比
- Python 实现快排
- 忘记区块链技术,融入区块链思维
- 阿里云服务器ECS带宽计费模式租用价格表
- SDUT Round #4 - 2018 新春大作战 官方题解(保留版)
- 涡旋光束基本概念介绍
- MySQL 常用内置函数与所有内置函数