openstack学习之RPC服务实现分析

来源:互联网 发布:淘宝网天猫女鞋 编辑:程序博客网 时间:2024/05/17 08:11
openstack中的服务主要有两种:一种是rest服务,提供Rest API;一种RPC服务,提供RPC API。本文讨论RPC服务的实现。Rest服务的实现在《openstack学习之各种API》有所涉及。

RPC服务其实就是一个RPC server,client(客户)可以通过RPC API进行调用。以nova为例,nova中的多数服务(service)都是一个RPC server。比如nova-conductor,nova-compute,nova-consoleauth,nova-scheduler...等

实现一个rpc server需要几个部分:
1)启动命令代码
2)Service定义
3)Manager定义
4)功能实现代码
其中1)2)3)属于框架性代码,每个rpc server的实现都差不多;4)和rpc server要实现的功能相关。

以nova为例,来分析这些部分的实现。
nova.cmd package中定义了所有服务的启动代码,包括rpc server和rest api服务。api.py,api_ec2.py,api_metadata.py,api_os_compute.py是rest api服务。这个目录中还包含了一些命令工具(utility command),如manage.py。读者可自行查看。

rpc server的启动代码基本类似:
1)定义main
2) 加载配置文件
3) 配置log
4) 创建server对象
5)启动service.

步骤4的代码compute:
    server = service.Service.create(binary='nova-compute',
                                    topic=CONF.compute_topic,
                                    db_allowed=CONF.conductor.use_local)
步骤4的代码schduler:
    server = service.Service.create(binary='nova-scheduler',
                                    topic=CONF.scheduler_topic)
步骤4的代码conductor:
    server = service.Service.create(binary='nova-conductor',
                                    topic=CONF.conductor.topic,
                                    manager=CONF.conductor.manager)
步骤5的代码,3者一致
    service.serve(server)
    service.wait()

Service对象
Service位于nova.service.py
该对象继承于nova.openstack.common.service.py中的Service

__init__方法
初始化几个重要的成员
        self.host = host
        self.binary = binary
        self.topic = topic
        self.manager_class_name = manager

参数有启动命令提供。host如果没有传入,从配置文件读取。host = CONF.host

start方法:
该方法用来启动rpc server。
该方法的主要功能就是创建RPC队列并绑定到exchang上。
        target = messaging.Target(topic=self.topic, server=self.host)
        endpoints = [
            self.manager,
            baserpc.BaseRPCAPI(self.manager.service_name, self.backdoor_port)
        ]
        endpoints.extend(self.manager.additional_endpoints)

target用来指定该rpc server监听在哪些队列上。
target指定了2个参数:topic和server。查看target代码(olso.messaging: oslo.messaging.target.py)
    :param server: Clients can request that a message be directed to a specific
      server, rather than just one of a pool of servers listening on the topic.
    :param topic: A name which identifies the set of interfaces exposed by a
      server. Multiple servers may listen on a topic and messages will be
      dispatched to one of the servers in a round-robin fashion.

底层如何使用target创建RPC队列并绑定到exchang上,可以查看代码
transport._listen
  self._driver.listen(target)
amqpdriver.listen
  conn.declare_topic_consumer(target.topic, listener)
  conn.declare_topic_consumer('%s.%s' % (target.topic, target.server),
                                    listener)
  conn.declare_fanout_consumer(target.topic, listener)
从代码中可以看到创建了3个队列,这个3个系列用来实现《openstack学习之RPC》提到的3种RPC场景
随机调用某server上的一个方法: 通过第一个队列实现
调用某特定server上的一个方法: 通过第二个队列实现,这个队列通过server参数来唯一标识一个队列
调用所有server上的一个方法:通过第三个队列实现,exchange type为fantout类型
关于队列的概念可以参考另一篇博文《openstack学习之RPC》

endpoints用来定义该rpc server支持哪些API。
manager中部分方法其实就是RPC API的方法,比如ComputeManager中有reboot_instance,这个方法就是一个RPC API。

client调用RCP API时会给出topic,方法名,方法参数等信息。oslo.messaging中的RPCDispatch会根据这些信息将该请求直接转化为对manager的相应方法的调用,并将方法参数准备好。

还可以看到openstack会给每个rpc server加一个额外的API(BaseRPCAPI),这个API目前只有一个ping方法。openstack内部会用这个方法检测一个服务是否已经启动完毕,如果启动完毕,就可以相应ping调用。

Service对象还提供了另外一个功能,定时任务。
            self.tg.add_dynamic_timer(self.periodic_tasks,
                                     initial_delay=initial_delay,
                                     periodic_interval_max=
                                        self.periodic_interval_max)
self.periodic_tasks会调用manager.periodic_tasks。

综上,Service对象的核心功能就是创建监听队列,并将收到的消息转化为对manager对象的方法调用。每个openstack项目实现都有定义一个自己的Service对象(如nova.service.py,cinder.service.py,neutron.service.py),这些对象的代码基本类似,相信后边社区会对这些代码进行重构。

Manager对象

如前所述,Manager对象其实就是RPC API的入口。每个RPC API最终会转化为对Manger相应方法的调用,这个方法就是该RPC API的最终实现。

每个服务都会有一个相应的Manager对象,因为一般每个服务所提供的API都是不同的。每个服务的实现都会有一个相应的python package(文件系统中的目录),如conductor,compute,consoleauth,scheduler等。每个package中又会有一个manager.py。这个manager.py就定义了这个服务的Manager对象。如compute.manager.py定义了ComputeManager。nova boot命令最终会调用这个对象中的run_instance方法。
要想进一步看懂Manager中的代码,就需要对相应问题领域(problem domain,也就是我们常说的业务流程)比较熟悉了。ComputeManager是处理虚拟机生命周期的,我们要对虚拟机有了解,才能读懂其中的代码。

掌握了Service + Manager,基本上就了解了RPC server是如何工作的,学习openstack代码就比较直观了。



0 0
原创粉丝点击