分布式监控系统(类zabbix)

目录:

为什么要做监控?

监控系统业务需求分析;

监控系统架构设计;

监控系统表结构设计;

 

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

市面上已经有很多成熟的监控系统,例如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年的监控数据?(趋势图展示)  

7.数据可视化,如何做出简洁美观的用户界面?

 
8.如何实现单机支持5000+机器监控需求?

 

6.安装、部署,支持主动/被动监控。

a.可在client端上安装agent插件,向server端主动汇报监控信息(主动监控)

b.可以通过server端去抓取client端监控数据(被动监控)

 

 

 

三、监控系统架构设计

 

 

client 向server 获取自己的监控配置项

1.server DB存储客户端配置信息
2.client定时去服务器获取配置信息(更新配置项)


client 向server 汇报监控数据

1.客户端通过命令获取返回值
2.组织数据汇报监控数据给Django,然后Django打时间戳把监控信息存到redis
3.Django在把监控信息存到redis的同时会触发 1个数据优化存储程序、阀值判断和报警程序
4.Monitor Data Handler去redis轮训检测哪个主机 没有汇报信息;

 

 

 

四、监控系统表结构设计

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

转载于:https://www.cnblogs.com/sss4/p/9375595.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值