一、需求讨论

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. C#生成JOSN字符串

    C#如何生成JSON字符串?(序列化对象)   第一章:C#如何拿到从http上返回JSON数据? 第二章:C#如何解析JSON数据?(反序列化对象) 第三章:C#如何生成JSON字符串?(序列化对象 ...

  2. SSIS的部署和配置

    参考:http://www.cnblogs.com/JasonLiao/p/SSISDeploy.htmlhttps://msdn.microsoft.com/en-us/library/ms1401 ...

  3. SQLServer之数据类型解析

    数字 int.bigint.smallint 和 tinyint 使用整数数据的精确数字数据类型. 数据类型 范围 存储 tinyint 0 到 255. 1 字节 smallint -2^15 (- ...

  4. (转载)Python之道1-环境搭建与pycharm的配置django安装及MySQL数据库配置

    近期做那个python的开发,今天就来简单的写一下开发路线的安装及配置, 开发路线 Python3.6.1+Pycharm5.0.6+Django1.11+MySQL5.7.18 1-安装Python ...

  5. Docker: 企业级镜像仓库Harbor的使用

    上一节,演示了Harbor的安装部署 这次我们来讲解 Harbor的使用. 我们需要了解到: 1. 如何推镜像到镜像仓库 2. 如何从镜像仓库拉取镜像 3. 如何运行从私有仓库拉取的镜像 # 查看 h ...

  6. 5.机器学习——DBSCAN聚类算法

    1.优缺点 优点: (1)聚类速度快且能够有效处理噪声点和发现任意形状的空间聚类: (2)与K-MEANS比较起来,不需要输入要划分的聚类个数: (3)聚类簇的形状没有偏倚: (4)可以在需要时输入过 ...

  7. Ambari——大数据平台的搭建利器之进阶篇

    前言 本文适合已经初步了解 Ambari 的读者.对 Ambari 的基础知识,以及 Ambari 的安装步骤还不清楚的读者,可以先阅读基础篇文章<Ambari——大数据平台的搭建利器>. ...

  8. C# Json字符串保存信息

    1.我们在进行数据通信的时候,往往是需要传输一个字符串类型的参数,而这个字符串类型的参数又需要封装大量的数据信息. 这个时候,就需要使用Json来封装这些数据,最后将Json数据以字符串的格式输出 2 ...

  9. .net core下用HttpClient和asp.net core实现https的双向认证

    关于https双向认证的知识可先行google,这时矸接代码. 为了双向认证,我们首先得准备两个crt证书,一个是client.crt,一个是server.crt,有时为了验证是否同一个根证书的验证, ...

  10. php curl cookie 读写

    普通 curl post 请求 public static function curlPost($url, $post_fields = array(), $timeout = 5) { $timeo ...