一、需求讨论

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、所以我要把传送接口约定好,内容包括

  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、代码实现

    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】:报警阈值程序逻辑解析(三)的更多相关文章

  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. Oracle——DQL、DML、DDL、DCL

    1.DQL:数据查询语言 基本结构:由select.from.where组成 子句组成的查询块:    SELECT <字段名表>    FROM <表或视图名>    WHE ...

  2. SpringBoot+Maven多模块项目(创建、依赖、打包可执行jar包部署测试)完整流程

    一,创建Maven多模块项目先建立外层父工程         File →new →project  选择Spring Initializr          Next下一步到以下页面 工程结构如下 ...

  3. C语言运行库翻译

    这是从Visual C++ 6里面的C语言部分翻译过来. http://files.cnblogs.com/files/sishenzaixian/C运行库.zip

  4. java-----理解java的三大特性之多态

    的java提高篇(四)-----理解的java的三大特性之多态 面向对象编程有三大特性:封装,继承,多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...

  5. kafka实战kerberos

    more /etc/krb5.conf [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log a ...

  6. CVS简单介绍

    版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Jerome_s/article/details/27990707 CVS - Concurrent Ver ...

  7. CentOS 6.5 minimal 安装配置VMware tools

    1.登录到系统,切换到root账户 2.配置网络 minimal版本默认不启动网络,所以要自己配置. 配置过程很简单,编辑配置文件 vi /etc/sysconfig/network-script/i ...

  8. linux性能监控命令(vmstat、sar、iostat、netstat)

    1.常用系统命令Vmstat.sar.iostat.netstat.free.ps.top等 2.常用组合方式• 用vmstat.sar.iostat检测是否是CPU瓶颈• 用free.vmstat检 ...

  9. 实验六:通过grub程序引导本地磁盘内核启动系统(busybox)

    实验名称: 通过grub程序引导本地磁盘内核启动系统(busybox) 实验环境: 理论上,该实验只需要配置好xen环境即可,但是,我们的xen环境安装在centOS7上,但是我们又是使用的kerne ...

  10. pyspider爬虫框架webui简介-爬取阿里招聘信息

    命令行输入pyspider开启pyspider 浏览器打开http://localhost:5000/ group表示组名,几个项目可以同一个组名,方便管理,当组名修改为delete时,项目会在一天后 ...