码迷,mamicode.com
首页 > 其他好文 > 详细

nova-conductor与AMQP(一)

时间:2014-10-29 21:06:39      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   os   ar   使用   for   

源码版本:H版

一、AMQP基础

1.1什么是AMQP?

可以参考如下文章:

http://blog.csdn.net/linvo/article/details/5750987

http://blog.csdn.net/gaoxingnengjisuan/article/details/11468061

 

1.2 nova中的AMQP

可以参考如下文章:

http://docs.openstack.org/developer/nova/devref/rpc.html

 

二、以nova-conductor为例具体分析

  凡是对外提供RPC调用的组件都会包含rpcapi.py文件,将这些调用放在该文件中。如果需要对这些组件进行rpc调用,只需导入这个rpcapi.py文件,然后创建相应的类,调用相应的函数。

  在rpcapi.py中一般API类的函数都是调用self.clent的cast函数或call函数发送消息。其中,cast函数是异步的,不需要返回结果,而call函数是同步的,需要等待结果返回。我们需要进一步了解这个self.client对象。在这些API类的构造函数中我们发现self.client对象都是通过self.get_client函数获得,由于这些API类都继承nova.rpcclient.RpcProxy类,所以其调用的get_client函数就是nova.rpcclient.RpcProxy中的get_client,该方法获得的实例为nova.rpcclient.RPCClient对象。总的来说,就是rpcapi.py中的类方法都是借用nova.rpcclient.RPCClient对象的cast或call进行消息的发送。

  以nova.conductor.rpcapi.ComputeTaskAPI的 build_instances函数为例,这里希望通过该api调用nova-conductor为我们建立虚拟机,进一步的分析如下:

def build_instances(self, context, instances, image, filter_properties,
            admin_password, injected_files, requested_networks,
            security_groups, block_device_mapping, legacy_bdm=True):
    instances_p = [jsonutils.to_primitive(inst) for inst in instances]
    image_p = jsonutils.to_primitive(image)
    cctxt = self.client.prepare(version=‘1.5‘)
    cctxt.cast(context, build_instances,
               instances=instances_p, image=image_p,
               filter_properties=filter_properties,
               admin_password=admin_password,
               injected_files=injected_files,
               requested_networks=requested_networks,
               security_groups=security_groups,
               block_device_mapping=block_device_mapping,
               legacy_bdm=legacy_bdm)

  根据上面的说明,cctxt.cast 实际为RPCClient的cast函数,如下:

def cast(self, ctxt, method, **kwargs):
    if self.server_params:
        def cast_to_server(ctxt, msg, **kwargs):
            if self.fanout:
                return self.proxy.fanout_cast_to_server(
                    ctxt, self.server_params, msg, **kwargs)
            else:
                return self.proxy.cast_to_server(
                    ctxt, self.server_params, msg, **kwargs)

        caster = cast_to_server
    else:
        """caster为ComputeTaskAPI实例的cast方法"""
        caster = self.proxy.fanout_cast if self.fanout else self.proxy.cast
    """调用caster方法"""
    self._invoke(caster, ctxt, method, **kwargs)

  RPCClient中的self.proxy指向处理rpc的代理,这里为ComputeTaskAPI类,说了半天其实创建了RPCClient,但是RPCClient又回来调用API类自身的cast方法。由于继承关系,直接进入nova.openstack.common.rpc.proxy.py中,调用RpcProxy的cast方法。如下:

def cast(self, context, msg, topic=None, version=None):
    self._set_version(msg, version)
    msg[args] = self._serialize_msg_args(context, msg[args])
    """其中rpc为nova.openstack.common.rpc"""
    rpc.cast(context, self._get_topic(topic), msg)

  进入nova/openstack/common/rpc/__init__.py模块,如下:

def cast(context, topic, msg):
    return _get_impl().cast(CONF, context, topic, msg)

  先看_get_impl()函数:

def _get_impl():
    global _RPCIMPL
    if _RPCIMPL is None:
        try:
            _RPCIMPL = importutils.import_module(CONF.rpc_backend)
        except ImportError:
            impl = CONF.rpc_backend.replace(nova.rpc,
                                            nova.openstack.common.rpc)
            _RPCIMPL = importutils.import_module(impl)
    return _RPCIMPL

  此处rpc_backend为qpid,进入nova/openstack/common/rpc/impl_qpid.py。由于AMQP后端的实现有多种,所以这里对各种后端实现进行封装,对外提供统一的接口。且看cast函数:

def cast(conf, context, topic, msg):
    return rpc_amqp.cast(
        conf, context, topic, msg,
        rpc_amqp.get_connection_pool(conf, Connection))

  rpc_amqp.get_connection_pool(conf, Connection)可以获取AMQP连接池,这个连接池和具体的AMQP后端实现对应,接着来看该cast方法,其为nova.openstack.common.amqp.cast,主要内容为从连接池中建立连接,然后使用impl_qpid.py中的Connection连接发送消息。后面的处理过程可以参考:

http://blog.csdn.net/gaoxingnengjisuan/article/details/12230521。主要内容就是建立创建TopicPublisher并绑定exchange,然后发送消息。

  总结流程图如下:

bubuko.com,布布扣

  在消息队列的使用中,最关键的是exchange和topic,其确定了消息将发送至哪个队列,也就确定了消息将由哪个组件的哪个函数处理。所有的nova服务组件启动时都会设置exchange为nova,使用哪个组件的rpcapi.py文件中的类就会将topic初始化为该组件的topic,每个组件的topic具体内容会在/etc/nova/nova.conf中进行配置。这样exchange和topic就共同确定了消息的处理流程!!!

 

nova-conductor与AMQP(一)

标签:style   blog   http   io   color   os   ar   使用   for   

原文地址:http://www.cnblogs.com/littlebugfish/p/4058007.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!