Ceilometer项目源码分析----ceilometer分布式报警系统的具体实现(1)

感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!

如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn

PS:最近没有登录博客,很多朋友的留言没有看见,这里道歉!还有就是本人较少上QQ,可以邮件交流。


ceilometer分布式报警系统的具体实现(1)

    在前面的博客中,我们分析过在/ceilometer/alarm/service.py中实现了类PartitionedAlarmService,它的主要功能是实现了分布式报警系统服务的启动和其他操作,当时我们只是从整体上分析了分布式报警系统的启动和实现,而分布式报警系统各个操作的具体实现则是在/ceilometer/alarm/partition/coordination.py中的类PartitionCoordinator中,所以这篇博客将会详细地分析分布式报警系统的具体实现,即分析类PartitionCoordinator中各个方法的源码实现。


1 def _distribute(self, alarms, rebalance)

def _distribute(self, alarms, rebalance):
    """
    实现对报警器的分配操作;              
    如果需要对全部报警器执行重新分配操作,self.coordination_rpc.assign(对所有的报警器进行分配操作):
    通过广播发送执行assign操作的通知给所有的Partition,在所有的Partition执行接收操作;在接收操作中,如果uuid和某Partition相应的uuid值相匹配,则该Partition实现赋值本alarms的ID值到其本地;
    如果不需要对全部报警器执行重新分配操作,self.coordination_rpc.allocate(只对部分(新增)的报警器进行分配操作,所以某个Partition上可有多余1个的报警器):
    通过广播发送执行allocate操作的通知给所有的Partition,在所有的Partition执行接收操作;在接收操作中,如果uuid和某Partition相应的uuid值相匹配,则该Partition实现添加本alarms的ID值到其本地;
    """
    verb = 'assign' if rebalance else 'allocate'
        
    """
    根据rebalance的值,来确定所要执行的分配报警器的方法;
    如果需要对全部报警器重新分配操作,则调用self.coordination_rpc.assign;
    如果不需要对全部报警器重新分配操作,则调用self.coordination_rpc.allocate;
        
    self.coordination_rpc.assign:
    通过广播发送执行assign操作的通知给所有的Partition,
    在所有的Partition执行接收操作;
    在接收操作中,如果uuid和某Partition相应的uuid值相匹配,
    则该Partition实现赋值本alarms的ID值到其本地;
    self.coordination_rpc.allocate:
    通过广播发送执行allocate操作的通知给所有的Partition,
    在所有的Partition执行接收操作;
    在接收操作中,如果uuid和某Partition相应的uuid值相匹配,
    则该Partition实现添加本alarms的ID值到其本地;
    """

    method = (self.coordination_rpc.assign if rebalance
              else self.coordination_rpc.allocate)
    LOG.debug(_('triggering %s') % verb)
    LOG.debug(_('known evaluators %s') % self.reports)
        
    """
    计算每个evaluator上所要分配的报警器数目;
    """
    per_evaluator = int(math.ceil(len(alarms) /
                        float(len(self.reports) + 1)))
    LOG.debug(_('per evaluator allocation %s') % per_evaluator)
        
    """
    获取所有的evaluator;
    对所有的evaluator进行洗牌操作;
    """
    evaluators = self.reports.keys()
    random.shuffle(evaluators)
    offset = 0
        
    """
    遍历所有的evaluator;
    """
    for evaluator in evaluators:
        if self.oldest < self.this:
            LOG.warn(_('%(this)s bailing on distribution cycle '
                       'as older partition detected: %(older)s') %
                     dict(this=self.this, older=self.oldest))
            return False
   
        """
        从所有报警器集合中获取一个报警器;
        """
        allocation = alarms[offset:offset + per_evaluator]
            
        """
        调用之前确定的分配方法,实现对报警器的分配操作;
        self.coordination_rpc.assign:
        通过广播发送执行assign操作的通知给所有的Partition,
        在所有的Partition执行接收操作;
        在接收操作中,如果uuid和某Partition相应的uuid值相匹配,
        则该Partition实现赋值本alarms的ID值到其本地;
        self.coordination_rpc.allocate:
        通过广播发送执行allocate操作的通知给所有的Partition,
        在所有的Partition执行接收操作;
        在接收操作中,如果uuid和某Partition相应的uuid值相匹配,
        则该Partition实现添加本alarms的ID值到其本地;
        """
        if allocation:
            LOG.debug(_('%(verb)s-ing %(alloc)s to %(eval)s') %
                      dict(verb=verb, alloc=allocation, eval=evaluator))
            method(evaluator.uuid, allocation)
            
        """
        为下一个报警器的获取做准备;
        """
        offset += per_evaluator
    LOG.debug(_('master taking %s for self') % alarms[offset:])
        
    """
    对于本Partition所分配的报警器的实现;
    """
    if rebalance:
        self.assignment = alarms[offset:]
    else:
        self.assignment.extend(alarms[offset:])
    return True
方法小结:

实现对报警器的分配操作;
1.如果需要对全部报警器执行重新分配操作,self.coordination_rpc.assign(对所有的报警器进行分配操作):
  通过广播发送执行assign操作的通知给所有的Partition,在所有的Partition执行接收操作;在接收操作中,如果uuid和某Partition相应的uuid值相匹配,则该Partition实现赋值本alarms的ID值到其本地;
2.如果不需要对全部报警器执行重新分配操作,self.coordination_rpc.allocate(只对部分(新增)的报警器进行分配操作,所以某个Partition上可有多余1个的报警器):
  通过广播发送执行allocate操作的通知给所有的Partition,在所有的Partition执行接收操作;在接收操作中,如果uuid和某Partition相应的uuid值相匹配,则该Partition实现添加本alarms的ID值到其本地;


2 def _deletion_requires_rebalance(self, alarms)

def _deletion_requires_rebalance(self, alarms):
    """
    通过获取最新已删除的报警器数据,来确定是否需要执行rebalance操作;
    如果已删除的报警器数据多余当前报警器数据的五分之一,则返回True,说明需要执行rebalance操作;
    """
    # 获取最新已经删除的报警器集合;
    deleted_alarms = self.last_alarms - set(alarms)
    LOG.debug(_('newly deleted alarms %s') % deleted_alarms)
        
    # 存储最新的已删除的报警器数据;
    self.deleted_alarms.update(deleted_alarms)
        
    # 如果已删除的报警器数据多余当前报警器数据的五分之一,则返回True,说明需要执行rebalance操作;
    if len(self.deleted_alarms) > len(alarms) / 5:
        LOG.debug(_('alarm deletion activity requires rebalance'))
        self.deleted_alarms = set()
        return True
    return False
方法小结:

通过获取最新已删除的报警器数据,来确定是否需要执行rebalance操作;
如果已删除的报警器数据多余当前报警器数据的五分之一,则返回True,说明需要执行rebalance操作;


3 def _is_master(self, interval)

def _is_master(self, interval):
    """
    确定当前的partition是否是主控角色;
    """
    now = timeutils.utcnow()
    if timeutils.delta_seconds(self.start, now) < interval * 2:
        LOG.debug(_('%s still warming up') % self.this)
        return False
        
    is_master = True
    for partition, last_heard in self.reports.items():
        delta = timeutils.delta_seconds(last_heard, now)
        LOG.debug(_('last heard from %(report)s %(delta)s seconds ago') %
                  dict(report=partition, delta=delta))
        if delta > interval * 2:
            del self.reports[partition]
            self._record_oldest(partition, stale=True)
            LOG.debug(_('%(this)s detects stale evaluator: %(stale)s') %
                      dict(this=self.this, stale=partition))
            self.presence_changed = True
        elif partition < self.this:
            is_master = False
            LOG.info(_('%(this)s sees older potential master: %(older)s')
                     % dict(this=self.this, older=partition))
    LOG.info(_('%(this)s is master?: %(is_master)s') %
             dict(this=self.this, is_master=is_master))
    return is_master

4 def _master_role(self, assuming, api_client)

def _master_role(self, assuming, api_client):
    """
    作为拥有主控权的partition,根据不同的情况实现不同形式的报警器分配操作;
    1.需要整个分布式报警系统的重平衡操作
      如果assuming为True,说明此报警器为新进的分布式报警系统的主控节点(所以需   
      要整个分布式报警系统的重平衡操作);
      如果sufficient_deletion为True,说明已删除的报警器数据多余当前报警器数据的   
      五分之一(变化过多,所以需要整个分布式报警系统的重平衡操作);
      如果presence_changed为True,则说明需要执行整个分布式报警系统的重平衡操作;
    2.对部分报警器(新建立报警器)实现重平衡操作;
    3.对于其他情况,不需要进行报警器的分配操作;
    """
        
    """
    通过客户端获取当前所有partition的报警器;
    """
    alarms = [a.alarm_id for a in api_client.alarms.list()]
        
    """
    获取新建立的报警器;
    当前的报警器集合减去之前的报警器集合,得到新建立的报警器;
    """
    created_alarms = list(set(alarms) - self.last_alarms)
    LOG.debug(_('newly created alarms %s') % created_alarms)
        
    """
    通过获取最新已删除的报警器数据,来确定是否需要执行rebalance操作;
    如果已删除的报警器数据多余当前报警器数据的五分之一,则返回True,说明需要执
    行rebalance操作;
    """
    sufficient_deletion = self._deletion_requires_rebalance(alarms)
        
    """
    如果assuming为True,说明此报警器为新进的分布式报警系统的主控节点(所以需要
    整个分布式报警系统的重平衡操作);
    如果sufficient_deletion为True,说明已删除的报警器数据多余当前报警器数据的五
    分之一(变化过多,所以需要整个分布式报警系统的重平衡操作);
    如果presence_changed为True,则说明需要执行整个分布式报警系统的重平衡操作;
    """
    # _distribute:实现对报警器的分配操作;
    if (assuming or sufficient_deletion or self.presence_changed):
        still_ahead = self._distribute(alarms, rebalance=True)
            
    """
    对于新建立报警器,实现对报警器分配操作,不需要进行所有报警器的重新分配操作;
    """
    elif created_alarms:
        still_ahead = self._distribute(list(created_alarms),
                                       rebalance=False)
        
    """
    对于其他情况,不需要进行报警器的分配操作;
    """
    else:
        still_ahead = self.this < self.oldest
        
    """
    实现更新报警器的集合;
    """
    self.last_alarms = set(alarms)
    LOG.info(_('%(this)s not overtaken as master? %(still_ahead)s') %
            ({'this': self.this, 'still_ahead': still_ahead}))
    return still_ahead
方法小结:

作为拥有主控权的partition,根据不同的情况实现不同形式的报警器分配操作;
1.需要整个分布式报警系统的重平衡操作
  如果assuming为True,说明此报警器为新进的分布式报警系统的主控节点(所以需要整个分布式报警系统的重平衡操作);
  如果sufficient_deletion为True,说明已删除的报警器数据多余当前报警器数据的五分之一(变化过多,所以需要整个分布式报警系统的重平衡操作);
  如果presence_changed为True,则说明需要执行整个分布式报警系统的重平衡操作;
2.对部分报警器(新建立报警器)实现重平衡操作;
3.对于其他情况,不需要进行报警器的分配操作;


下篇博客将会进行继续解析~~~~

你可能感兴趣的:(源代码,openstack,ceilometer)