感謝朋友支持本博客,歡迎共同探討交流,由於能力和時間有限,錯誤之處在所難免,歡迎指正!
如果轉載,請保留作者信息。
博客地址: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'))