Ceilometer項目源碼分析----ceilometer-alarm-notifier服務的初始化和啓動

感謝朋友支持本博客,歡迎共同探討交流,由於能力和時間有限,錯誤之處在所難免,歡迎指正!

如果轉載,請保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
郵箱地址:[email protected]

PS:最近沒有登錄博客,很多朋友的留言沒有看見,這裏道歉!還有就是本人較少上QQ,可以郵件交流。


ceilometer-alarm-notifier服務的初始化和啓動

    在I版的ceilometer的各個服務組件啓動是在/ceilometer/cli.py中實現的,而在J版中,是在實體包/celiometer/cmd中實現的。結合配置文件setup.cfg中的內容,可見主要有以下幾個服務組件:
    console_scripts=
    ceilometer-api= ceilometer.cli:api
    ceilometer-agent-central= ceilometer.cli:agent_central
    ceilometer-agent-compute= ceilometer.cli:agent_compute
    ceilometer-agent-notification= ceilometer.cli:agent_notification
    ceilometer-send-sample= ceilometer.cli:send_sample
    ceilometer-dbsync= ceilometer.cli:storage_dbsync
    ceilometer-expirer= ceilometer.cli:storage_expirer
    ceilometer-collector= ceilometer.cli:collector_service
    ceilometer-alarm-evaluator= ceilometer.cli:alarm_evaluator
    ceilometer-alarm-notifier= ceilometer.cli:alarm_notifier
    以下幾篇博客,分別來關注一下比較重要服務組件的初始化和啓動過程。首先來看ceilometer-alarm-notifier的初始化和啓動過程,這個組件服務所實現的功能是,當報警器被觸發之後,發送相關的通知操作。

    來看方法/ceilometer/cli.py----def alarm_notifier,這個方法即實現了ceilometer-alarm-notifier的初始化和啓動操作;

def alarm_notifier():
    """
    初始化並啓動AlarmNotifierService服務(報警器被觸發的通知服務);
    """
    service.prepare_service()
    
    """
    launch:加載並啓動指定的服務,最終調用了服務的start方法實現服務的啓動;
    AlarmNotifierService:報警器被觸發的通知服務實現;
    AlarmNotifierService():獲取類AlarmNotifierService的實例化對象,並實現加載EXTENSIONS_NAMESPACE對應的所有插件;
    """
    os_service.launch(alarm_service.AlarmNotifierService(
        cfg.CONF.host, 'ceilometer.alarm')).wait()

方法小結:

    1 實現AlarmNotifierService類的初始化操作,在類的初始化過程中會加載命名空間ceilometer.alarm.notifier所定義的所有插件,確定所有實現通知操作的實現方式;

    2 launch方法最終會調用類AlarmNotifierService的start方法,實現組件服務的啓動操作;


1 服務ceilometer-alarm-notifier的初始化

class AlarmNotifierService(rpc_service.Service):
    """
    報警器被觸發的通知服務實現;
    """
    EXTENSIONS_NAMESPACE = "ceilometer.alarm.notifier"

    def __init__(self, host, topic):
        """
        host = cfg.CONF.host
        topic = 'ceilometer.alarm'
        
        獲取類AlarmNotifierService的實例化對象;
        並實現加載EXTENSIONS_NAMESPACE對應的所有插件;
        ceilometer.alarm.notifier =
            log = ceilometer.alarm.notifier.log:LogAlarmNotifier
            test = ceilometer.alarm.notifier.test:TestAlarmNotifier
            http = ceilometer.alarm.notifier.rest:RestAlarmNotifier
            https = ceilometer.alarm.notifier.rest:RestAlarmNotifier
        """
        super(AlarmNotifierService, self).__init__(host, topic, self)
       self.notifiers = extension.ExtensionManager(self.EXTENSIONS_NAMESPACE,                                   invoke_on_load=True)

方法小結:

    實現AlarmNotifierService類的初始化操作,在類的初始化過程中會加載命名空間ceilometer.alarm.notifier所定義的所有插件,確定所有實現通知操作的實現方式;

    ceilometer.alarm.notifier=
    log= ceilometer.alarm.notifier.log:LogAlarmNotifier
    test= ceilometer.alarm.notifier.test:TestAlarmNotifier
    http= ceilometer.alarm.notifier.rest:RestAlarmNotifier
    https= ceilometer.alarm.notifier.rest:RestAlarmNotifier

    定義了通知操作的實現方式,即記錄報警器觸發信息到日誌和通過http/https協議實現發送報警器觸發信息。


2 服務ceilometer-alarm-notifier的啓動

class AlarmNotifierService----def start

class AlarmNotifierService(rpc_service.Service):
    def start(self):
        """              
        服務的啓動;
        爲RPC通信建立到信息總線的連接;
        1.建立指定類型的消息消費者;       
        2.執行方法initialize_service_hook,建立一個'topic'類型的消息消費者;
        3.啓動協程實現等待並消費處理隊列中的消息;
        """
        super(AlarmNotifierService, self).start()
        # Add a dummy thread to have wait() working
        self.tg.add_timer(604800, lambda: None)

方法小結:

    服務的啓動,爲RPC通信建立到信息總線的連接;

    1.建立指定類型的消息消費者;
    2.執行方法initialize_service_hook,建立一個'topic'類型的消息消費者;

    3.啓動協程實現等待並消費處理隊列中的消息;


class Service----def start

class Service(service.Service):
    def start(self):
        """
        爲RPC通信建立到信息總線的連接;
        1.建立指定類型的消息消費者;       
        2.執行方法initialize_service_hook;
        3.啓動協程實現等待並消費處理隊列中的消息;
        """
        super(Service, self).start()

        """
        爲RPC通信建立到信息總線的連接;
        建立一個新的連接,或者從連接池中獲取一個;
        """
        self.conn = rpc.create_connection(new=True)
        LOG.debug(_("Creating Consumer connection for Service %s") %
                  self.topic)

        """
        RpcDispatcher:RPC消息調度類;
        """
        dispatcher = rpc_dispatcher.RpcDispatcher([self.manager],
                                                  self.serializer)

        """
        create_consumer:建立指定類型的消息消費者(fanout or topic);
        1.創建以服務的topic爲路由鍵的消費者;
        2.創建以服務的topic和本機名爲路由鍵的消費者
          (基於topic&host,可用來接收定向消息);
        3.fanout直接投遞消息,不進行匹配,速度最快
          (fanout類型,可用於接收廣播消息);
        """
        self.conn.create_consumer(self.topic, dispatcher, fanout=False)
        node_topic = '%s.%s' % (self.topic, self.host)
        self.conn.create_consumer(node_topic, dispatcher, fanout=False)
        self.conn.create_consumer(self.topic, dispatcher, fanout=True)

        """
        在消息消費進程啓動前,必須先聲明消費者;
        建立一個'topic'類型的消息消費者;
        根據消費者類(TopicConsumer)和消息隊列名稱
        (pool_name:  ceilometer.collector.metering)
        以及指定主題topic(metering)建立消息消費者,並加入消費者列表;
        """
        if callable(getattr(self.manager, 'initialize_service_hook', None)):
            self.manager.initialize_service_hook(self)

        """
        啓動消費者線程;
        consume_in_thread用evelent.spawn創建一個協程一直運行;
        等待消息,在有消費到來時會創建新的協程運行遠程調用的函數;
        啓動協程實現等待並消費處理隊列中的消息;
        """
        self.conn.consume_in_thread()


class AlarmNotifierService----def initialize_service_hook

class AlarmNotifierService(rpc_service.Service):
    def initialize_service_hook(self, service):
        """
        建立一個'topic'類型的消息消費者;
        指定主題topic(alarm_notifier)和隊列名稱pool_name(ceilometer.alarm.alarm_notifier);
        """
        LOG.debug(_('initialize_service_hooks'))
        self.conn.create_worker(
            # alarm_notifier
            cfg.CONF.alarm.notifier_rpc_topic,
            rpc_dispatcher.RpcDispatcher([self]),
            # ceilometer.alarm.alarm_notifier
            'ceilometer.alarm.' + cfg.CONF.alarm.notifier_rpc_topic,
        )


3 類AlarmNotifierService中的方法notify_alarm

    方法notify_alarm是具體實現報警器觸發後的發送通知操作的具體方法,當報警器被觸發之後,都會調用這個方法,主要實現了以下內容:
    遍歷所有要通知報警器被觸發的URL,針對每個要通知的URL地址,實現:
    1 獲取系統所採用的消息通信方式;
    2 通過HTTP/HTTPS協議POST方法實現發送相關報警器被觸發的通知(到action指定的URL),(or)通過日誌記錄相關報警器被觸發的通知;

def notify_alarm(self, context, data):
    """
    遍歷所有要通知報警器被觸發的URL,針對每個要通知的URL地址,實現:
    1.獲取系統所採用的消息通信方式;
    2.通過HTTPS協議POST方法實現發送相關報警器被觸發的通知(到action指定的URL),(or)通過日誌記錄相關報警器被觸發的通知;              
        
    通知報警器被觸發,通知內容中包括:
    alarm_id:被觸發的報警器的ID;
    previous:報警器(觸發)之前的狀態;
    current:報警器被觸發後轉換到的新狀態;
    reason:改變報警器狀態的原因;
    """
    actions = data.get('actions')
    if not actions:
        LOG.error(_("Unable to notify for an alarm with no action"))
        return

    # actions:要運行的action的URL(多個);
    # alarm_id:被觸發的報警器的ID;
    # previous:報警器(觸發)之前的狀態;
    # current:報警器被觸發後轉換到的新狀態;
    # reason:改變報警器狀態的原因;
    for action in actions:
        """
        獲取系統所採用的消息通信方式;
        通過HTTPS協議POST方法實現發送相關報警器被觸發的通知(到action指定的URL),(or)通過日誌記錄相關報警器被觸發的通知;
        """
        self._handle_action(action,
                            data.get('alarm_id'),
                            data.get('previous'),
                            data.get('current'),
                            data.get('reason'),
                            data.get('reason_data'))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章