分布式监控系统开发【day38】:报警阈值程序逻辑解析(三)
一、需求讨论
1、请问如何解决延迟问题
1000台机器,每1分钟循环一次但是刚好第一次循环第一秒刚处理完了,结果还没等到第二分钟又出问题,你那必须等到第二次循环,假如我这个服务很重要必须实时知道,
每次客户端汇报过来的同时,触发trigger检测,就可以实时的实现报警反应
2、这样有什么问题?
前提是它给你汇报,如果客户端网络断了,客户端宕机了,就无法汇报了
3、你要确保客户端存活的检测机制
拿到每台机器的所有触发器,检测阈值,如果超过阈值,存到redis
你不用再连redis我给你传(从外部调用 时才用的到,为了避免重复调用 redis连接)
二、那个表达式触发了报警?
1、开发目标为红框内内容
2、触发报警函数功能
- def load_service_data_and_calulating()的功能如下:
- [ iowait.avg(5) >10 and ,idle < 20 or ,mem_usage > 80% and, disk > 90% ]
- 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、实现代码
- def load_service_data_and_calulating(self,host_obj,trigger_obj,redis_obj):
- '''
- fetching out service data from redis db and calculate according to each serivce's trigger configuration
- :param host_obj:
- :param trigger_obj:
- :param redis_obj: #从外面调用此函数时需传入redis_obj,以减少重复连接
- :return:
- '''
- #StatusData_1_LinuxCPU_10mins
- self.redis = redis_obj
- calc_sub_res_list= [] #先把每个expression的结果算出来放在这个列表里,最后再统一计算这个列表
- positive_expressions = [] #报警的时候,让用户知道,那些条件导致触发报警器成立
- expression_res_string = '' #最终拼成的表达式运算字符串
- for expression in trigger_obj.triggerexpression_set.select_related().order_by('id'):
- print(expression,expression.logic_type)
- expression_process_obj = ExpressionProcess(self,host_obj,expression)
- single_expression_res = expression_process_obj.process() #得到单条expression表达式的结果
- if single_expression_res:
- calc_sub_res_list.append(single_expression_res)
- if single_expression_res['expression_obj'].logic_type: #不是最后一条
- expression_res_string += str(single_expression_res['calc_res']) + ' ' + \
- single_expression_res['expression_obj'].logic_type + ' '
- else:
- expression_res_string += str(single_expression_res['calc_res']) + ' '
- #把所有结果为True的expression提出来,报警时你得知道是谁出问题导致trigger触发了
- if single_expression_res['calc_res'] == True:
- single_expression_res['expression_obj'] = single_expression_res['expression_obj'].id #要存到redis里,数据库对象转成id
- positive_expressions.append(single_expression_res)
- #else: #single expression不成立,随便加个东西,别让程序出错,这个地方我觉得是个bug
- # expression_res_string += 'None'
- print("whole trigger res:", trigger_obj.name,expression_res_string)
- if expression_res_string:
- trigger_res = eval(expression_res_string)
- print("whole trigger res:", trigger_res )
- if trigger_res:#终于走到这一步,该触发报警了
- print("##############trigger alert:",trigger_obj.severity,trigger_res)
- self.trigger_notifier(host_obj,trigger_obj.id, positive_expressions,msg=trigger_obj.name) #msg 需要专门分析后生成, 这里是临时写的
三、故障持续了多久?
1、开发目标
2、功能如下:
1、连接上 redis连接,双方已经是生产这消费者模式
2、所以我要把传送接口约定好,内容包括
- host_id:那台主机
- trigger_id:哪一个触发器,
- positive_expressions:哪一个表达式触发的报警
- msg:消息
- time: 什么时候报警的
- start_time:什么时间开始的
- duration:故障持续多久了
3、发不到订阅的频道TRIGGER_CHAN = 'trigger_event_channel'
4、为什么是pickle?
- 我的ositive_expressions里面存的是什么东西,是实例
- redis里面肯定存不成实例,所以我以字符串的形式存进去,json序列化不了实例
5、先把之前的trigger加载回来,获取上次报警的时间,以统计 故障持续时间
6、同时在redis中记录这个trigger , 前端页面展示时要统计trigger 个数
7、一个trigger 记录5分钟后会自动清除, 为了在前端统计trigger个数用的
3、代码实现
- def trigger_notifier(self,host_obj,trigger_id, positive_expressions,redis_obj=None,msg=None):
- '''
- all the triggers alerts need to be published through here
- :param host_obj:
- :param trigger_id:
- :param positive_expressions: it's list, contains all the expression has True result
- :param redis_obj:
- :return:
- '''
- #alert.sendmail(msg )
- #alert.sendsms(msg)
- if redis_obj: #从外部调用 时才用的到,为了避免重复调用 redis连接
- self.redis = redis_obj
- print("\033[43;1mgoing to send alert msg to trigger queue............\033[0m")
- print('trigger_notifier argv:',host_obj,trigger_id, positive_expressions,redis_obj)
- #
- msg_dic = {'host_id':host_obj.id,
- 'trigger_id':trigger_id,
- 'positive_expressions':positive_expressions,
- 'msg':msg,
- 'time': time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()),
- 'start_time':time.time() ,
- 'duration':None
- }
- self.redis.publish(self.django_settings.TRIGGER_CHAN, pickle.dumps(msg_dic))
- #先把之前的trigger加载回来,获取上次报警的时间,以统计 故障持续时间
- trigger_redis_key = "host_%s_trigger_%s" % (host_obj.id, trigger_id)
- old_trigger_data = self.redis.get(trigger_redis_key)
- print("old_trigger_data",old_trigger_data)
- if old_trigger_data:
- old_trigger_data = old_trigger_data.decode()
- trigger_startime = json.loads(old_trigger_data)['start_time']
- msg_dic['start_time'] = trigger_startime
- msg_dic['duration'] = round(time.time() - trigger_startime)
- #同时在redis中纪录这个trigger , 前端页面展示时要统计trigger 个数
- self.redis.set(trigger_redis_key, json.dumps(msg_dic), 300) #一个trigger 纪录 5分钟后会自动清除, 为了在前端统计trigger个数用的
分布式监控系统开发【day38】:报警阈值程序逻辑解析(三)的更多相关文章
- Python之路,Day20 - 分布式监控系统开发
Python之路,Day20 - 分布式监控系统开发 本节内容 为什么要做监控? 常用监控系统设计讨论 监控系统架构设计 监控表结构设计 为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个 ...
- 分布式监控系统开发【day38】:报警自动升级代码解析及测试(八)
一.报警自动升级代码解析 发送邮件代码 def action_email(self,action_obj,action_operation_obj,host_id,trigger_data): ''' ...
- 分布式监控系统开发【day37】:需求讨论(一)
本节内容 为什么要做监控? 常用监控系统设计讨论 监控需求讨论 如何实现监控服务器的水平扩展? 监控系统架构设计 一.为什么要做监控? 熟悉IT监控系统的设计原理 开发一个简版的类Zabbix监控系统 ...
- Python之分布式监控系统开发
为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个简版的类Zabbix监控系统 –掌握自动化开发项目的程序设计思路及架构解藕原则 常用监控系统设计讨论 Zabbix Nagios 监控系统需求 ...
- day26 分布式监控系统开发
本节内容 为什么要做监控? 常用监控系统设计讨论 监控系统架构设计 监控表结构设计 为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个简版的类Zabbix监控系统 –掌握自动化开发项目的程序设 ...
- 分布式监控系统开发【day38】:报警策略设计(二)
一.策略和动作多对多的好处坏处 1.好处: 相同服务,相同策略的服务可以不用重复写好多次触发器 2.坏处: 1.策略A给小李和小罗发邮件2.策略B给小胡和小崔发邮件3.策略A是第三部发邮件4.策略B是 ...
- 分布式监控系统开发【day38】:报警策略队列处理(五)
一.目录结构 二.报警策略队列处理 1.入口MonitorServer import os import sys if __name__ == "__main__": os.env ...
- 分布式监控系统开发【day38】:主机存活检测程序解析(七)
一.目录结构 二.入口 1.文件MonitorServer.py import os import sys if __name__ == "__main__": os.enviro ...
- 分布式监控系统开发【day38】:监控trigger表结构设计(一)
一.需求讨论 1.zabbix触发器的模板截图 1.zabbix2.4.7 2.zabbix3.0 2.模板与触发器关联的好处 好处就是可以批量处理,比如我说我有1000机器都要监控cpu.内存.IO ...
随机推荐
- iOS 防止离屏渲染为 image 添加圆角
// image 分类 - (UIImage *)circleImage{ // NO 代表透明 UIGraphicsBeginImageContextWithOptions(self.siz ...
- 【记录】Xmind8 Pro 激活
摘要 XMind 是一个全功能的思维导图和头脑风暴软件,为激发灵感和创意而生.作为一款有效提升工作和生活效率的生产力工具,受到全球百千万用户的青睐. [有能力请支持正版] 在xmin下载xmi ...
- 我的第一个python web开发框架(25)——定制ORM(一)
在开始编写ORM模块之前,我们需要先对db_helper进行重构,因为ORM最终生成的sql是需要转给db_helper来执行的,所以拥有一个功能完善.健壮的数据库操作类是非常必要的. 这是项目原db ...
- insert into select的实际用法
INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table ...
- 解析Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值. 定义对象可以使用构造函数或字面量的形式: 除了以上添加属性的方式,还可以使用Object.defineProperty定义新属性 ...
- 3.18 总结 java 基础语法
- 第1章 初始Docker容器
1.1 什么是Docker slogan:Build Ship Run Any App Anywher.关键在于Ship,通过把程序和程序运行所需要的环境一起交付. Linux容器技术: Docker ...
- 利用SQL注入漏洞登录后台
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...
- 移动端无限滚动 TScroll.vue组件
// 先看使用TScroll.vue的几个demo 1.https://sorrowx.github.io/TScroll/#/ 2. https://sorrowx.github.io/TScrol ...
- 利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库)
利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库),完成预期的任务,大致有下面几步: 1.代码提交到github平台 2.创建.podspec 3. ...