夜莺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发明合法按需处理条件告警事件(包括调整、推送、存储、升级、屏蔽等)。

这里有一个问题:为社么从Jugdepush到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告警主要有两大模块,JudgemonapiJudge将指标与策略结合生成告警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相关推荐

  1. 夜莺(Flashcat)V6监控(五):夜莺监控k8s组件(上)

        目录 (一)Kubernetest监控体系 1.Kubernetes监控策略 (二)K8s-ApiServer组件监控 (1)我们先创建一个namespace来专门做夜莺监控采集指标 (2)创 ...

  2. 更换jdk版本_滴滴夜莺发布 v3 版本,从运维监控演化成了运维平台

    Nightingale 从 3 月份开源到现在,过去了半年多点时间,收获了接近 2000 个 github star,300 多个 issue 升级说明 v3.x的版本和v2.x差别巨大,没办法平滑迁 ...

  3. 夜莺监控( Nightingale ),看这一篇就够了。(介绍、部署、配置、优化、自定义)

    文章目录 夜莺监控( Nightingale ) 概述 技术选型 categraf 简介 产品对比 nightingale 简介 系统架构 产品对比 Prometheus 简介 特点 组件介绍 架构规 ...

  4. 01.夜莺监控简介及安装

    夜莺监控系统介绍 夜莺监控( Nightingale )是一款国产.开源云原生监控分析系统,采用 All-In-One 的设计,集数据采集.可视化.监控告警.数据分析于一体.于 2020 年 3 月 ...

  5. 夜莺监控之Categraf监控VMwareVSphere

    之前一直在使用开源的虚拟化软件PVE(Proxmox VE),突然有一天网桥莫名其妙的出幺蛾子,周末鼓捣了半天,谷歌百度也找不到对应的解决方案,重新安装烦的不行,后来一怒之下就换了VMware的VSp ...

  6. Nightingale滴滴夜莺监控系统入门(五)--采集功能

    Nightingale滴滴夜莺监控系统入门(五)–采集功能 不知不觉夜莺已经更新到3.6版本,后续会议3.6来演示夜莺支持采集[端口][进程][日志][自定义插件]以及在3.5版本以后支持的主动采集[ ...

  7. redis缓存实现原理php,分析redis原理及实现

    下面由Redis教程栏目给大家介绍分析redis原理及实现,希望对需要的朋友有所帮助! 1 什么是redis redis是nosql(也是个巨大的map) 单线程,但是可处理1秒10w的并发(数据都在 ...

  8. 性能测试监控指标和分析

    一.软件性能测试需要监控哪些关键指标? 软件性能测试的目的主要有以下三点: 1.评价系统当前性能,判断系统是否满足预期的性能需求. 2.寻找软件系统可能存在的性能问题,定位性能瓶颈并解决问题. 3.判 ...

  9. 手把手教你搭建Nightingale夜莺监控系统

    ⚠:我依旧是那个不懂技术的小白! 俗话说:无监控不运维! 我身为一个运维界的小白!最常用的监控有:Zabbix,Prometheus,Nagios,CACTI ,夜莺,以及小米的开源监控open-fa ...

最新文章

  1. 55、组播配置实验之PIM Sparse Mode静态指定RP
  2. bitcask存储引擎
  3. BZOJ2653 middle 【主席树】【二分】*
  4. 设计模式-模板模式-个人理解
  5. 字节3-1前端面试官自学Vue的正确姿势
  6. [JavaWeb-JavaScript]JavaScript_Math数学对象
  7. 中国游戏公司研运一体发展专题分析2020
  8. Meta Company在公开信中谴责Facebook改名
  9. android驱动在win10系统上安装的心酸历程
  10. 写一个自己的javascript库
  11. 无线路由器与交换机配合使用,图解
  12. 薪资16K,进华为外包怎么样?
  13. vue中如何设置鼠标经过切换样式
  14. 程序员在跳槽时,该怎么说离职原因?
  15. html+css发光字体
  16. 冰刃(IceSword)的使用方法(高级篇)
  17. Html5 1.4 figure和figcaption的实例
  18. 二十二、商城 - 商品录入-FastDFS(10)
  19. 专访王威廉:NLP哪些研究方向更容易取得突破?
  20. 使用SPSS进行多元回归分析

热门文章

  1. 4g网络什么时候淘汰_5G时间表已出4G会被淘汰吗 4g网络还能用多久
  2. 2021年12月中国车企新能源汽车销量排行榜:Top前三的车企销量远超于其他车企,且市场份额占比均超过10%(附月榜TOP68详单)
  3. Transformer课程 第46章 Transformer模型TAPAS架构
  4. 管理批量邮箱 FOXMAIL 和网易闪电邮(PC端)有什么区别? 对比
  5. Python 实现快排
  6. 忘记区块链技术,融入区块链思维
  7. 阿里云服务器ECS带宽计费模式租用价格表
  8. SDUT Round #4 - 2018 新春大作战 官方题解(保留版)
  9. 涡旋光束基本概念介绍
  10. MySQL 常用内置函数与所有内置函数