您的位置:首页 > 运维架构

分布式监控系统(类zabbix)

2018-07-27 09:13 393 查看

目录:

为什么要做监控?

监控系统业务需求分析;

监控系统架构设计;

监控系统表结构设计;

 

一、为什么要做监控系统?

市面上已经有很多成熟的监控系统,例如zabbix、nagios,为什么自己开发监控系统?

1.提示个人开发能力;

2.熟悉成熟监控系统的设计思想、架构、解耦原则;

3.调用 zabbix/openfalcon/nagios的API进行个人开发定制;

 

 

 

 二、监控系统业务需求分析

1、可以监控常用系统服务、应用、网络设备等;

硬件层面:

  服务器温度、磁盘RAID阵列......

系统层面:

  存活状态、CPU、RAM、load负载

应用层:

  mysql、Nginx、Django、LVS、HAProxy

业务层面:

  PV、UV、订单

 

2、1台服务器上可以监控N个不同的服务、不同的服务汇报监控数据的时间间隔也不同;(例如CPU负载过高60分钟汇报1次、Nginx服务端口是否关闭3分钟汇报1次)

 

3.同1个服务在不同被监控机器的监控间隔、报警的阀值可不同(不同被监控机器的性能不同)

 

4.可以批量的给一批机器 添加、删除、修改监控项;

 

5.告警级别:

  • 不同的服务 因为业务重要程度不同,如果出了问题可以设置不同的报警级别
  • 可以指定特定的服务或告警级别的事件通知给特定的用户
  • 告警的升级设定

 

6.历史数据 的存储和优化
  • 实现用最少的空间占用量存储最多的有效数据
  • 如何做到1s中之内取出一台主机上所有服务的5年的监控数据?(趋势图展示)
    from django.db import models
    from django.db import models
    from django.contrib.auth.models import User
    
    class Host(models.Model):
    '''被监控主机表  '''
    name=models.CharField(max_length=64,unique=True,verbose_name='主机名') #唯一
    ipaddr=models.GenericIPAddressField(unique=True,verbose_name='IP地址')
    host_groups=models.ManyToManyField('HostGroup',blank=True,verbose_name='主机组')  #1台主机可以同时属于多个whatever 主机组
    templates=models.ManyToManyField('Template',blank=True,verbose_name='所属模板') #主机和模板直接 多 对 多,可以给单台主机 定制模板
    monitored_by_choices = (
    ('agent', 'Agent'),
    ('snmp', 'SNMP'),
    ('wget', 'WGET'),
    )
    monitored_by = models.CharField(max_length=64, choices=monitored_by_choices,verbose_name='监控方式')
    status_choices = (
    (1, 'Online'),
    (2, 'Down'),
    (3, 'Unreachable'),
    (4, 'Offline'),
    (5, 'Problem'),
    )
    status = models.IntegerField(choices=status_choices, default=1,verbose_name='存活状态')
    host_alive_check_interval = models.IntegerField(default=30, verbose_name='主机存活状态检测间隔')
    memo = models.TextField(blank=True,null=True,verbose_name='备注信息')
    
    class HostGroup(models.Model):
    '''被监控主机 组  '''
    name =  models.CharField(max_length=64,unique=True)
    templates = models.ManyToManyField("Template",blank=True) #组可以有模板,方便批量管理、操作; 主机也可以有模板
    memo = models.TextField(blank=True,null=True,verbose_name="备注")
    
    class ServiceIndex(models.Model):
    '''监控的服务的 正常指标列表'''
    name = models.CharField(max_length=64,verbose_name='指标名称')
    key =models.CharField(max_length=64,verbose_name='cpu idle')
    data_type_choices = (#客户端汇报的监控信息的数据类型
    ('int',"int"),
    ('float',"float"),
    ('str',"string")
    )
    data_type = models.CharField(max_length=32,choices=data_type_choices,default='int',verbose_name='指标数据类型')
    memo = models.CharField(max_length=128,blank=True,null=True,verbose_name="备注")
    
    class Service(models.Model):
    '''监控的某项服务'''
    name = models.CharField(max_length=64,unique=True,verbose_name='服务名称')
    interval = models.IntegerField(default=60,verbose_name='监控间隔')
    plugin_name = models.CharField(max_length=64,default='n/a',verbose_name='插件名')
    items = models.ManyToManyField('ServiceIndex',blank=True,verbose_name="指标列表",)#1个CPU服务可能有多个指标
    has_sub_service = models.BooleanField(default=False,help_text="如果一个服务还有独立的子服务 ,选择这个,比如 网卡服务有多个独立的子网卡") #如果一个服务还有独立的子服务 ,选择这个,比如 网卡服务有多个独立的子网卡
    memo = models.CharField(max_length=128,blank=True,null=True,verbose_name="备注",)
    
    class Template(models.Model):
    name = models.CharField(max_length=64,unique=True,verbose_name='模版名称')
    services = models.ManyToManyField('Service',verbose_name="服务列表")  #1个模板监控多个服务,1个服务属于多个模板
    triggers = models.ManyToManyField('Trigger',verbose_name="触发器列表",blank=True)#哪个服务
    
    class TriggerExpression(models.Model):
    '''
    触发器表达式
    if cpu.idle(avg(5mins)) < 80% and
    cpu.iowait(hit(10,3)) > 50%  = warning
    
    1 trigger1   cpu.idle(avg(5mins)) < 80% and
    2 trigger1  cpu.iowait(hit(10,3)) > 50%
    通过trigger关联:查询出当前trigger的所有触发器表达式,从上到下按顺序执行!
    
    '''
    trigger = models.ForeignKey('Trigger',verbose_name="所属触发器")  #1个触发器表方式(条件)只能属于1个触发器
    service = models.ForeignKey(Service,verbose_name="关联服务")
    service_index = models.ForeignKey(ServiceIndex,verbose_name="关联服务指标")
    specified_index_key = models.CharField(verbose_name="只监控专门指定的指标key",max_length=64,blank=True,null=True)
    operator_type_choices = (('eq','='),('lt','<'),('gt','>'))
    operator_type = models.CharField("运算符",choices=operator_type_choices,max_length=32)
    data_calc_type_choices = (
    ('avg','Average'),
    ('max','Max'),
    ('hit','Hit'),
    ('last','Last'),
    )
    data_calc_func= models.CharField(verbose_name="数据处理方式",choices=data_calc_type_choices,max_length=64)
    data_calc_args = models.CharField(verbose_name="函数传入参数",help_text="若是多个参数,则用,号分开,第一个值是时间",max_length=64)
    threshold = models.IntegerField(verbose_name="阈值")
    
    logic_type_choices = (('or','OR'),('and','AND'))
    logic_type = models.CharField(verbose_name="与一个条件的逻辑关系",choices=logic_type_choices,max_length=32,blank=True,null=True)
    
    class Meta:
    pass #unique_together = ('trigger_id','service')
    
    class Trigger(models.Model):
    '''触发器表  '''
    name = models.CharField(u'触发器名称',max_length=64)
    severity_choices = (
    (1,'Information'),
    (2,'Warning'),
    (3,'Average'),
    (4,'High'),
    (5,'Diaster'),
    )
    #expressions = models.ManyToManyField(TriggerExpression,verbose_name=u"条件表达式")
    severity = models.IntegerField(u'告警级别',choices=severity_choices)
    enabled = models.BooleanField(default=True)
    memo = models.TextField(verbose_name="备注",blank=True,null=True)
    
    class Action(models.Model):
    '''报警方式  '''
    name =  models.CharField(max_length=64,unique=True)
    host_groups = models.ManyToManyField('HostGroup',blank=True)
    hosts = models.ManyToManyField('Host',blank=True)
    triggers = models.ManyToManyField('Trigger',blank=True,help_text="想让哪些trigger触发当前报警动作")
    interval = models.IntegerField(u'告警间隔(s)',default=300)
    operations = models.ManyToManyField('ActionOperation',verbose_name='允许报警升级的设置!')
    
    recover_notice = models.BooleanField(u'故障恢复后发送通知消息',default=True)
    recover_subject = models.CharField(max_length=128,blank=True,null=True)
    recover_message = models.TextField(blank=True,null=True)
    enabled = models.BooleanField(default=True)
    
    class ActionOperation(models.Model):
    name =  models.CharField(max_length=64)
    step = models.SmallIntegerField(verbose_name="第n次告警",default=1)
    action_type_choices = (
    ('email','Email'),
    ('sms','SMS'),
    ('script','RunScript'),
    )
    action_type = models.CharField(verbose_name="动作类型",choices=action_type_choices,default='email',max_length=64)
    notifiers= models.ManyToManyField('UserProfile',verbose_name="通知对象",blank=True)
    _msg_format = '''Host({hostname},{ip}) service({service_name}) has issue,msg:{msg}'''
    
    msg_format = models.TextField(verbose_name="消息格式",default=_msg_format)
    
    class Maintenance(models.Model):
    '''预维护计划  '''
    name =  models.CharField(max_length=64,unique=True)
    hosts = models.ManyToManyField('Host',blank=True)
    host_groups = models.ManyToManyField('HostGroup',blank=True)
    content = models.TextField(verbose_name="维护内容")
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    
    class UserProfile(models.Model):
    user = models.OneToOneField(User)
    name = models.CharField(max_length=32)
    phone = models.BigIntegerField(blank=True,null=True)
    weixin = models.CharField(max_length=64,blank=True,null=True)
    email = models.EmailField(blank=True,null=True)
    models.py

     

     

     

    五、项目实战

    5.1:监控客户端开发

    功能:

    1.监控客户端定时向server端更新监控配置信息;

    2.server端响应client{插件名称:汇报间隔},客户端 定期执行该插件向server端汇报监控数据(开始监控);

     

     

    5.2:接收监控数据汇报API开发

    功能

    1.server端接收到监控数据之后 加上时间戳,存入redis,并进行数据优化存储;(优化:计算N个点的平均值、max、min、中位数,合并N个点为1个点)

    2.存储优化数据之后,定时 遍历实时数据和触发器正在做对比,判断是否需要触发报警?触发报警通过redis队列发布一条消息到报警中心;

     

     

    5.3:报警中心开发

    功能

    1.报警信息汇报之后,信息优化存储、对比触发器阈值,触发报警;(每次客户端主动汇报监控信息时,被动触发。)

    2.主动监测客户端是否按时向server端汇报数据?报警信息合并、收敛;(主动触发报警)

    3.根据不同报警通知到相关责任人

     

     

    5.4: 图表展示优化后的监控数据

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    参考:

    https://www.cnblogs.com/alex3714/articles/5450798.html

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: