背景

2016年小米贡献了Open-Falcon V0.1 版本,并且迅速在各互联网公司传播和改进,当时我只是看了一下文档,并没有直接运用到我们的监控系统。

2017年Open-Falcon社区很热闹,官方网站进行了全新改版,更具国际范,而且6月17日V0.2版本也即将发布,决定尝试在我们的IDC部署和使用最新的版本。

其中的Alarm组件只考虑到短信告警和邮件告警,对于当前微信、QQ以及各种企业级IM泛滥的今天,有些欠缺。虽然看到github中有人修改了Alarm的几行代码,借用短信发送方法,将后台存储的用户手机号改为微信账号,完成微信告警,但同时也带来短信告警和IM告警不能相互独立,决定遵循原有架构下扩展Alarm组件,使短信告警、IM告警和邮件告警相对独立并且可并存。

需要指出的是,Alarm组件最终只是产生告警信息并调用配置文件中的外部http接口,外部接口去实现im消息发送,短信发送和邮件发送,我会在另外一篇博文中介绍如何使用改进后的Alarm组件配合微信企业号发送后台服务,完成微信告警信息的发送。

Open-Falcon 的源代码地址

Open-Falcon V0.1 https://github.com/open-falcon-archive/of-release

Open-Falcon V0.2 https://github.com/open-falcon/falcon-plus

修改说明

本文涉及的源代码更改,已经提交 PR 到社区,并已被合并到Open-Falcon V0.2 中,只需要更新最新的代码即可,如有使用上的任何问题或者改进建议可随时联系我。

Alarm组件的扩展

主要思路

下面主要说明一下这次扩展Alarm的思路:

Open-Falcon的后台数据库中,保存了用户的基本信息,其中除了手机和邮箱外,已经包含IM字段用于保存IM账号,需要说明的是IM账号可以是微信,QQ,钉钉等,可以根据各自企业的IT环境和需求自行选择。所以扩展Alarm组件,从用户的IM字段中读取信息,生成告警信息后,调用用户配置的IM告警后端发送接口,就可以完成此次扩展。

Alarm组件的包结构

alarm
  |-api            提供自身或其他组件的调用api
  |-cron           存放定时执行的告警发送任务
  |-g              读取组件配置文件、执行组件和写入日志
  |-http           组件自身提供的http接口,回复组件是否正常工作
  |-model          定义用到的数据模型
    |-event        定义存储在后台数据库中的event
  |-redi           和redis有关的操作
  cfg.example.json 组件的配置文件示例

Alarm组件的运作流程

  1. 读取Redis中由Judge组件存放到redis中的判定需要告警的信息;
  2. 将告警事件写入后台数据库的event_cases表,并写入redis;
  3. 短信和邮件发送线程从redis中读取告警事件;
  4. 将告警信息写入后台数据库的events表;
  5. 由于考虑到发送短信或者邮件的数量过多会淹没重要的告警信息,所以将低优先级的告警信息(Priority>=3)会合并成一条告警信息,并告知连接地址,访问Dashboard组件,查看明细信息。
  6. 将合并后的告警信息写入redis的短信告警队列或者邮件告警队列;
  7. 短信发送线程读取redis的短信告警队列,并根据配置文件中的http接口地址,调用发送短信;
  8. 邮件发送线程读取redis的邮件告警队列,并根据根据配置文件中的http接口地址,调用发送告警邮件;
  9. 定期删除数据库中7天以前的告警事件;

Alarm组件的配置文件说明

由于open-falcon使用json格式的配置文件,不能增加注释,也导致使用者往往需要看代码后才知道如何配置,为了便于大家理解配置文件,所以下面的注释是我自己加的,不能直接将内容复制到配置文件中,会导致程序无法读取配置文件。

{
    "log_level": "debug", #设置组件的日志输出级别,运行在生产环境下,需要设置为info或者warn
    "http": {
        "enabled": true, #允许通过http访问确认alarm服务是否正常
        "listen": "0.0.0.0:9912"  #设置http服务的访问端口
    },
    "redis": {
        "addr": "127.0.0.1:6379", #redis服务地址
        "maxIdle": 5, #设置最大有多少个空闲实例
        "highQueues": [
            "event:p0", #告警最高级别p0
            "event:p1", 
            "event:p2"
        ],
        "lowQueues": [
            "event:p3",
            "event:p4",
            "event:p5",
            "event:p6"  #告警最低级别p6
        ],
        "userIMQueue": "/queue/user/im",  #redis中存放发送IM的告警信息的队列
        "userSmsQueue": "/queue/user/sms",  #redis中存放发送sms的告警信息的队列
        "userMailQueue": "/queue/user/mail"  #redis中存放发送mail的告警信息的队列
    },
    "api": {
        "im": "http://127.0.0.1:10086/wechat", #设置发送IM的服务接口
        "sms": "http://127.0.0.1:10086/sms",   #设置发送sms的服务接口
        "mail": "http://127.0.0.1:10086/mail",  #设置发送mail的服务接口
        "dashboard": "http://127.0.0.1:8081",  #dashboard组件的服务地址
        "plus_api":"http://127.0.0.1:8080", #plus的api地址
        "plus_api_token": "default-token-used-in-server-side" #plus的api token
    },
    "falcon_portal": {
        "addr": "root:@tcp(127.0.0.1:3306)/alarms?charset=utf8&loc=Asia%2FChongqing", #后台数据库访问地址
        "idle": 10,  #空闲实例数
        "max": 100  #最大实例数
    },
    "worker": {
        "im": 10,  #发送im的线程数
        "sms": 10,  #发送sms的线程数
        "mail": 50  #发送mail的线程数
    },
    "housekeeper": {
        "event_retention_days": 7,  #清除数据库中超过七天的告警事件
        "event_delete_batch": 100  #每次清除100条
    }
}

Alarm组件的具体改动

  • 修改modules/alarm/api/uic.go的ParseTeams方法,增加返回IM字符串数组;
  • 修改modules/alarm/cfg.example.json,增加了三行:

    "userIMQueue": "/queue/user/im",

    "im": "http://127.0.0.1:10086/wechat",

    "im": 10,

    其中 http://127.0.0.1:10086/wechat 是需要另外开发基于微信接口的发送服务后台,我会在另外一篇博文中介绍。
  • 增加modules/alarm/cron/builder.go的BuildCommonIMContent和GenerateIMContent函数;
  • 修改modules/alarm/cron/callback.go的HandleCallback函数;
  • 修改modules/alarm/cron/event_consumer.go的consumeHighEvents函数;
  • 增加modules/alarm/cron/im_sender.go
  • 增加modules/alarm/model/im.go
  • 修改modules/alarm/cron/init_sender.go的InitSenderWorker函数;
  • 修改modules/alarm/g/cfg.go的读取新增加的配置信息
  • 修改modules/alarm/main.go的main函数,增加调用发送im消息的函数;
  • 增加modules/alarm/redi/msg_reader.go的PopAllIM函数;
  • 增加modules/alarm/redi/msg_writer.go的WriteIMModel和WriteIM函数;