zoukankan      html  css  js  c++  java
  • 为自己的系统定制openstack ceilometer

    一、目的

    最近研究了一下ceilometer,目的做一个监控系统,对系统中发生的事件进行处理。ceilometer对openstack各个组件信息的收集方式主要由 推 和  拉 两种。

    “推”: 就是openstack的各个组件将信息以notification的形式发送到message bus,然后有agent_notification对消息进行监听,agent_notification 在接收到消息后,经过一个pipeline的处理,然后再通过rpc发送给collector,

    collector负责将接收这些消息并且存储到持久化介质中,如 database,file等;这样中间会经过两次rpc的发送;

    “拉”:  openstack ceilometer会部署compute agent 还有 central agent 来主动的轮询(polling)一些组件的信息,compute agent主要负责收集虚拟机 cpu 内存、io等信息,compute agent会部署到每个虚拟机上,compute agent定期通过hyperviser api去获取信息。central agent 只部署在控制节点上,负责收集其他的信息image ,network等等,是通过restfulapi的方式调用;两种agent收集到消息后也是发送到rpc,然后collector收集;

    二、设计方案

    回到我们项目的需求上,我们只需要收集系统中的事件(event),其实ceilometer对收集信息的定义包括event和sample,event 就是一件发生的事情(例如: intance.create),sample是事件发生过程的产生的具体数据,(例如,为了instance分配了多少memory)。我们的系统中只需要处理event不用处理sample。所以删除了对sampe部分的处理。

    第二个改动是,我们这边只有notification发出的消息,也就是只有推的机制,没有拉的机制,这样,其实就可以考虑不用对notification两次rpc传输了。考虑agent_notification接受到消息后直接存储到数据库,将collector做的事情放到agent_notification中,但最终程序的名字还是叫collector。。。。上图


    系统中的各个组件通过notification api 发送消息到message bus(rabbit mq),collector通过监听一定的exchange和topic来获取notification信息,

    然后交给预先定义好的函数(event process pipeline)来处理,最后通过dispatcher转存储到持久化介质中;其中的event definition部分通过event_definition.yaml 来进行控制;

    三、示例sample

     (1) 发送notification消息,

    具体请参见higgs/sample/manager.py中的_sample_notify_period函数
    from openstack.common.notifier import api as notifier_api
    …...
    payload = {
                    'samples': [
                                {
                                    'name': 'test_notify_sample',
                                    'type': 'gauge',
                                    'unit': 'ns',
                                    'volume': 1,
                                }
                                ],
                    'reason': 'delete',
                    'user_id': 'test',
                    'tenant_id':'test',
                    'instance_id':'1234567890',
                }
     
     
    publisher_id = notifier_api.publisher_id('higgs_sample')
    notifier_api.notify(context,publisher_id,'compute.instance.test.samples',notifier_api.CONF.default_notification_level,payload)
    ……
     

     字段的具体定义如下:

    a) publisher_id 是数据的发送方,openstack中是指"the source worker_type.host of the message, e.g. ‘compute.host1’ “, 

    获取值的顺序是 CONF.host > CONF.default_publisher_id > socket.gethostname(),也可以通过notifier_api的publisher_id来进行设置;
     
    b) ‘compute.instance.test.samples’: 这个值是event_type,是string类型;如果要定义和发送一个新的事件,就起一个新的名字,例如:’scheduler.trigger’
     
    c) payload:中文释义是“装载” 顾名思义,就是发送一个事件时附带的详细信息,这个参数比较重要,collector中对事件的处理大部分的信息都是从payload中获取的;

    d) CONF.default_notification_level 默认的notification级别,级别为 DEBUG < INFO < WARNING < ERROR < CRITICAL;
     

    (2)collector中对事件的处理

     
     collector对事件的处理是通过yaml文件可配置的,具体的定义在event_definition.yaml中,截取一部分如下:
    - event_type: compute.instance.*
      traits: &instance_traits
        tenant_id:
          fields: payload.tenant_id
        user_id:
          fields: payload.user_id
        instance_id:
          fields: payload.instance_id
        host:
          fields: publisher_id
          plugin:
            name: split
            parameters:
              segment: 1
              max_split: 1
        service:
          fields: publisher_id
          plugin: split
        memory_mb:
          type: int
          fields: payload.memory_mb
        disk_gb:
          type: int
          fields: payload.disk_gb
    ....... 

    具体含义:
    a) event_type: 被识别的event_type名称,支持通配符,这里的意思是,凡是以compute.instance.开头的事件都会有这段逻辑来处理;
    traits: trait的中文是“特点”,可以理解为是一个event所携带的一个特点或者属性;例如trait下面的tenant_id、user_id......等都是一个trait;
     
    b) tenant_id:
          fields: payload.tenant_id 
    这两行一起看,表示这个trait的名字是tenant_id,它的值从你发送的event所携带的payload中的tenant_id中提取,payload.tenant_id的写法符合jsonpath https://pypi.python.org/pypi/jsonpath/ 
     
    c) host:
          fields: publisher_id
          plugin:
            name: split
            parameters:
              segment: 1
              max_split: 1 
    这七行一起看,这个trait的名字是host,它的值是从event的payload中的publisher_id这一项提取,不同的是,它要对提取的值进行一定的处理,调用name 为split的插件,给插件提供两个参数:
    segment和max_split;collector使用了stevedore来增加可拓展性,split的具体定义可以在setup.cfg中进行查看;
    如果需要自己发送的event进行特殊的处理,可以自己仿照着写插件;
     
    d) memory_mb:
          type: int
          fields: payload.memory_mb
    这三行一起看,与前两个不同的是,有一个type参数。这个type是针对trait而言的,trait有四种类型,string、int、float、datetime;如果没有实际写明type的类型,默认是string类型; 
     

    总之,如果你有一个新的event要处理,首先你要定义这个event中的重要信息,然后在event_definition.yaml中写一个类似的将event转成trait的处理单元;

    四、数据库结构

     
     
    简单的介绍下 event 和 trait的数据库结构,对于理解这个两个概念更有好处;
    event
    +---------------+---------------+------+-----+---------+----------------+
    | Field         | Type          | Null | Key | Default | Extra          |
    +---------------+---------------+------+-----+---------+----------------+
    | id            | int(11)       | NO   | PRI | NULL    | auto_increment |
    | message_id    | varchar(50)   | YES  | UNI | NULL    |                |
    | event_type_id | int(11)       | YES  | MUL | NULL    |                |
    | generated     | decimal(20,6) | YES  | MUL | NULL    |                |
    +---------------+---------------+------+-----+---------+----------------+
    每一个 event 都会有一个message_id,系统会默认生成,通过uuid;
    event_type_id是与另外一张event_type表相关联;
    generated是时间戳;
     
     
    event_type
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | desc  | varchar(255) | YES  | UNI | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    id表示event的type id,与event表中的event_type_id是外键关联;
     
    trait
    +---------------+---------------+------+-----+---------+----------------+
    | Field         | Type          | Null | Key | Default | Extra          |
    +---------------+---------------+------+-----+---------+----------------+
    | id            | int(11)       | NO   | PRI | NULL    | auto_increment |
    | t_string      | text          | YES  |     | NULL    |                |
    | t_float       | double        | YES  | MUL | NULL    |                |
    | t_int         | int(11)       | YES  | MUL | NULL    |                |
    | event_id      | int(11)       | YES  | MUL | NULL    |                |
    | trait_type_id | int(11)       | YES  | MUL | NULL    |                |
    | t_datetime    | decimal(20,6) | YES  | MUL | NULL    |                |
    +---------------+---------------+------+-----+---------+————————+
    t_ 开头表示trait的类型,在openstack中t_string是varchar(255),bsp考虑到可能会发送比较长的字符值,所以改成了text;
    event_id与event表中的id是外键关联;
    trait_type_id与trait_type表中的id是外键关联;
     
    trait_type
    +-----------+--------------+------+-----+---------+----------------+
    | Field     | Type         | Null | Key | Default | Extra          |
    +-----------+--------------+------+-----+---------+----------------+
    | id        | int(11)      | NO   | PRI | NULL    | auto_increment |
    | desc      | varchar(255) | YES  | MUL | NULL    |                |
    | data_type | int(11)      | YES  |     | NULL    |                |
    +-----------+--------------+------+-----+---------+————————+
    id 与 trait表中的trait_type_id是外键关联;

  • 相关阅读:
    opencv MAT数据操作
    浅谈模式识别中的特征提取
    设置Mysql的连接超时参数
    win7下怎样设置putty免用户名密码登陆
    正则表达式简明参考
    利用 canvas 破解 某拖动验证码
    wamp环境中mysql更改root密码
    Python读写文件
    Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
    如何改变placeholder的颜色
  • 原文地址:https://www.cnblogs.com/yuhan-TB/p/4054966.html
Copyright © 2011-2022 走看看