感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如果转载,请保留作者信息。
博客地址: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'))