一、需求讨论

1、请问如何解决延迟问题

1000台机器,每1分钟循环一次但是刚好第一次循环第一秒刚处理完了,结果还没等到第二分钟又出问题,你那必须等到第二次循环,假如我这个服务很重要必须实时知道,
每次客户端汇报过来的同时,触发trigger检测,就可以实时的实现报警反应

2、这样有什么问题?

前提是它给你汇报,如果客户端网络断了,客户端宕机了,就无法汇报了

3、你要确保客户端存活的检测机制

拿到每台机器的所有触发器,检测阈值,如果超过阈值,存到redis
你不用再连redis我给你传(从外部调用 时才用的到,为了避免重复调用 redis连接)

二、那个表达式触发了报警?

1、开发目标为红框内内容

2、触发报警函数功能

  1. def load_service_data_and_calulating()的功能如下:
  2. [ iowait.avg(5) >10 and ,idle < 20 or ,mem_usage > 80% and, disk > 90% ]
  3. exp_res_list = [] #[ True, False.True ]

1、到redis里取出5分钟的值,进行平均运算,得到的结果,与阈值【按定义的运算符】进行比较

2、拿到,每个表达式的结果,添加到exp_res_list,为什么要拿到结果?因为不是不是最后一条

3、拼接完整的表达式字符串 exp= "False and True and False and True"

4、我为什么不在这里顺手就报警了,这样不是很简单?

  你们学过生产消费者模型吗?为了解耦,另外就是异步

  我要考量到报警收敛,我可能一次批量报警,所以我就单独写一个报警模块

5、将成立的触发发送到报警队列

3、实现代码

  1. def load_service_data_and_calulating(self,host_obj,trigger_obj,redis_obj):
  2. '''
  3. fetching out service data from redis db and calculate according to each serivce's trigger configuration
  4. :param host_obj:
  5. :param trigger_obj:
  6. :param redis_obj: #从外面调用此函数时需传入redis_obj,以减少重复连接
  7. :return:
  8. '''
  9. #StatusData_1_LinuxCPU_10mins
  10. self.redis = redis_obj
  11. calc_sub_res_list= [] #先把每个expression的结果算出来放在这个列表里,最后再统一计算这个列表
  12. positive_expressions = [] #报警的时候,让用户知道,那些条件导致触发报警器成立
  13. expression_res_string = '' #最终拼成的表达式运算字符串
  14. for expression in trigger_obj.triggerexpression_set.select_related().order_by('id'):
  15. print(expression,expression.logic_type)
  16. expression_process_obj = ExpressionProcess(self,host_obj,expression)
  17. single_expression_res = expression_process_obj.process() #得到单条expression表达式的结果
  18. if single_expression_res:
  19. calc_sub_res_list.append(single_expression_res)
  20. if single_expression_res['expression_obj'].logic_type: #不是最后一条
  21. expression_res_string += str(single_expression_res['calc_res']) + ' ' + \
  22. single_expression_res['expression_obj'].logic_type + ' '
  23. else:
  24. expression_res_string += str(single_expression_res['calc_res']) + ' '
  25.  
  26. #把所有结果为True的expression提出来,报警时你得知道是谁出问题导致trigger触发了
  27. if single_expression_res['calc_res'] == True:
  28. single_expression_res['expression_obj'] = single_expression_res['expression_obj'].id #要存到redis里,数据库对象转成id
  29. positive_expressions.append(single_expression_res)
  30. #else: #single expression不成立,随便加个东西,别让程序出错,这个地方我觉得是个bug
  31. # expression_res_string += 'None'
  32. print("whole trigger res:", trigger_obj.name,expression_res_string)
  33. if expression_res_string:
  34. trigger_res = eval(expression_res_string)
  35. print("whole trigger res:", trigger_res )
  36. if trigger_res:#终于走到这一步,该触发报警了
  37. print("##############trigger alert:",trigger_obj.severity,trigger_res)
  38. self.trigger_notifier(host_obj,trigger_obj.id, positive_expressions,msg=trigger_obj.name) #msg 需要专门分析后生成, 这里是临时写的

三、故障持续了多久?

1、开发目标

2、功能如下:

1、连接上 redis连接,双方已经是生产这消费者模式

2、所以我要把传送接口约定好,内容包括

  1. host_id:那台主机
  2. trigger_id:哪一个触发器,
  3. positive_expressions:哪一个表达式触发的报警
  4. msg:消息
  5. time: 什么时候报警的
  6. start_time:什么时间开始的
  7. duration:故障持续多久了

3、发不到订阅的频道TRIGGER_CHAN = 'trigger_event_channel'

4、为什么是pickle?

  1. 我的ositive_expressions里面存的是什么东西,是实例
  2. redis里面肯定存不成实例,所以我以字符串的形式存进去,json序列化不了实例

5、先把之前的trigger加载回来,获取上次报警的时间,以统计 故障持续时间
6、同时在redis中记录这个trigger , 前端页面展示时要统计trigger 个数
7、一个trigger 记录5分钟后会自动清除, 为了在前端统计trigger个数用的

3、代码实现

  1. def trigger_notifier(self,host_obj,trigger_id, positive_expressions,redis_obj=None,msg=None):
  2. '''
  3. all the triggers alerts need to be published through here
  4. :param host_obj:
  5. :param trigger_id:
  6. :param positive_expressions: it's list, contains all the expression has True result
  7. :param redis_obj:
  8. :return:
  9. '''
  10.  
  11. #alert.sendmail(msg )
  12. #alert.sendsms(msg)
  13. if redis_obj: #从外部调用 时才用的到,为了避免重复调用 redis连接
  14. self.redis = redis_obj
  15. print("\033[43;1mgoing to send alert msg to trigger queue............\033[0m")
  16. print('trigger_notifier argv:',host_obj,trigger_id, positive_expressions,redis_obj)
  17. #
  18. msg_dic = {'host_id':host_obj.id,
  19. 'trigger_id':trigger_id,
  20. 'positive_expressions':positive_expressions,
  21. 'msg':msg,
  22. 'time': time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()),
  23. 'start_time':time.time() ,
  24. 'duration':None
  25. }
  26. self.redis.publish(self.django_settings.TRIGGER_CHAN, pickle.dumps(msg_dic))
  27.  
  28. #先把之前的trigger加载回来,获取上次报警的时间,以统计 故障持续时间
  29. trigger_redis_key = "host_%s_trigger_%s" % (host_obj.id, trigger_id)
  30. old_trigger_data = self.redis.get(trigger_redis_key)
  31. print("old_trigger_data",old_trigger_data)
  32. if old_trigger_data:
  33. old_trigger_data = old_trigger_data.decode()
  34. trigger_startime = json.loads(old_trigger_data)['start_time']
  35. msg_dic['start_time'] = trigger_startime
  36. msg_dic['duration'] = round(time.time() - trigger_startime)
  37.  
  38. #同时在redis中纪录这个trigger , 前端页面展示时要统计trigger 个数
  39.  
  40. self.redis.set(trigger_redis_key, json.dumps(msg_dic), 300) #一个trigger 纪录 5分钟后会自动清除, 为了在前端统计trigger个数用的

分布式监控系统开发【day38】:报警阈值程序逻辑解析(三)的更多相关文章

  1. Python之路,Day20 - 分布式监控系统开发

    Python之路,Day20 - 分布式监控系统开发   本节内容 为什么要做监控? 常用监控系统设计讨论 监控系统架构设计 监控表结构设计 为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个 ...

  2. 分布式监控系统开发【day38】:报警自动升级代码解析及测试(八)

    一.报警自动升级代码解析 发送邮件代码 def action_email(self,action_obj,action_operation_obj,host_id,trigger_data): ''' ...

  3. 分布式监控系统开发【day37】:需求讨论(一)

    本节内容 为什么要做监控? 常用监控系统设计讨论 监控需求讨论 如何实现监控服务器的水平扩展? 监控系统架构设计 一.为什么要做监控? 熟悉IT监控系统的设计原理 开发一个简版的类Zabbix监控系统 ...

  4. Python之分布式监控系统开发

    为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个简版的类Zabbix监控系统 –掌握自动化开发项目的程序设计思路及架构解藕原则 常用监控系统设计讨论 Zabbix Nagios 监控系统需求 ...

  5. day26 分布式监控系统开发

    本节内容 为什么要做监控? 常用监控系统设计讨论 监控系统架构设计 监控表结构设计 为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个简版的类Zabbix监控系统 –掌握自动化开发项目的程序设 ...

  6. 分布式监控系统开发【day38】:报警策略设计(二)

    一.策略和动作多对多的好处坏处 1.好处: 相同服务,相同策略的服务可以不用重复写好多次触发器 2.坏处: 1.策略A给小李和小罗发邮件2.策略B给小胡和小崔发邮件3.策略A是第三部发邮件4.策略B是 ...

  7. 分布式监控系统开发【day38】:报警策略队列处理(五)

    一.目录结构 二.报警策略队列处理 1.入口MonitorServer import os import sys if __name__ == "__main__": os.env ...

  8. 分布式监控系统开发【day38】:主机存活检测程序解析(七)

    一.目录结构 二.入口 1.文件MonitorServer.py import os import sys if __name__ == "__main__": os.enviro ...

  9. 分布式监控系统开发【day38】:监控trigger表结构设计(一)

    一.需求讨论 1.zabbix触发器的模板截图 1.zabbix2.4.7 2.zabbix3.0 2.模板与触发器关联的好处 好处就是可以批量处理,比如我说我有1000机器都要监控cpu.内存.IO ...

随机推荐

  1. iOS 防止离屏渲染为 image 添加圆角

        // image 分类 - (UIImage *)circleImage{ // NO 代表透明 UIGraphicsBeginImageContextWithOptions(self.siz ...

  2. 【记录】Xmind8 Pro 激活

    摘要 XMind 是一个全功能的思维导图和头脑风暴软件,为激发灵感和创意而生.作为一款有效提升工作和生活效率的生产力工具,受到全球百千万用户的青睐. [有能力请支持正版]     在xmin下载xmi ...

  3. 我的第一个python web开发框架(25)——定制ORM(一)

    在开始编写ORM模块之前,我们需要先对db_helper进行重构,因为ORM最终生成的sql是需要转给db_helper来执行的,所以拥有一个功能完善.健壮的数据库操作类是非常必要的. 这是项目原db ...

  4. insert into select的实际用法

    INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table ...

  5. 解析Object.defineProperty的作用

    对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值. 定义对象可以使用构造函数或字面量的形式: 除了以上添加属性的方式,还可以使用Object.defineProperty定义新属性 ...

  6. 3.18 总结 java 基础语法

  7. 第1章 初始Docker容器

    1.1 什么是Docker slogan:Build Ship Run Any App Anywher.关键在于Ship,通过把程序和程序运行所需要的环境一起交付. Linux容器技术: Docker ...

  8. 利用SQL注入漏洞登录后台

    所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...

  9. 移动端无限滚动 TScroll.vue组件

    // 先看使用TScroll.vue的几个demo 1.https://sorrowx.github.io/TScroll/#/ 2. https://sorrowx.github.io/TScrol ...

  10. 利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库)

    利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库),完成预期的任务,大致有下面几步: 1.代码提交到github平台 2.创建.podspec 3. ...