目录

方法注册

实例序列化与反序列化

conductor与数据库交互

Instance类对象与ComputeManager类对象

compute服务的worker数量

这里以instance.save函数为例进行说明。

方法注册

nova组件中compute服务访问DB的方式是通过Conductor服务来实现的,即通过indirection_api重定向到Conductor服务。

compute服务启动方法:

nova.cmd.compute.main

在该函数中初始化重定向api方法:

cmd_common.block_db_access('nova-compute')
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()

同时在nova.service.Service函数中,会等待conductor服务正常运行:

        if objects_base.NovaObject.indirection_api:conductor_api = conductor.API()conductor_api.wait_until_ready(context.get_admin_context())

因为构造Instance实例的时候,类的继承关系是:

oslo_versionedobjects.base.VersionedObject
--> nova.objects.base.NovaObject
--> nova.objects.instance.Instance

而indirection_api作为oslo_versionedobjects.base.VersionedObject成员变量,在nova.objects.instance.Instance中也是起到作用的,即调用instance的save()方法时,有一个@base.remotable装饰器,位于/nova/objects/instance.py

    @base.remotabledef save(self, expected_vm_state=None,expected_task_state=None, admin_state_reset=False):

通过这个装饰器,会判断self.indirection_api是否存在,上面已经赋值,因此可以在compute服务中通过indirection_api重定向到nova-conductor中。

@base.remotable装饰器源码位于:
oslo_versionedobjects.base.remotableif self.indirection_api:updates, result = self.indirection_api.object_action(ctxt, self, fn.__name__, args, kwargs)

前面indirection_api函数已经赋值,为conductor_rpcapi.ConductorAPI()

因此调用的方法是:nova.conductor.rpcapi.ConductorAPI.object_action

继而调用的方法是:

nova.conductor.rpcapi.ConductorAPI.object_action

PRC call的调用方法object_action

构造的target是:

target = messaging.Target(topic=RPC_TOPIC, version='3.0')
cctxt = self.client.prepare()

在prepare()中并未指定server,因此这里是想conductor队列发送消息。

假设由多个节点上同时运行conductor服务,则这几个节点上的conductor服务都会监听这个队列,但最终该消息会被其中一个conductor服务消费掉。

实例序列化与反序列化

消息在传输的时候,用的是字典类型的消息体作为消息传输的格式。但是在OpenStack组件中使用的都是对象实例,这些对象实例是怎么传输和接收的?这里以Instance对象实例为例进行介绍。

消息序列化

消息将要发送的时候,在oslo_messaging组件中都会调用如下的函数,将对象进行序列化:

self.serializer.serialize_entity=
nova.rpc.RequestContextSerializer.serialize_entity
(是nova.rpc.ProfilerRequestContextSerializer成员变量)
---> nova.objects.base.NovaObjectSerializer.serialize_entity

在该函数中,如果是对象实例的话,则会调用oslo_versionedobjects.base.VersionedObject.obj_to_primitive函数将对象实例转换为字典类型的数据,VersionedObject对象作为基类的继承关系如下所示:

oslo_versionedobjects.base.VersionedObject
--> nova.objects.base.NovaObject
--> nova.objects.instance.Instance

因此Instance对象中也有obj_to_primitive和_obj_from_primitive方法。

经过序列化之后的Instance对象实例如下所示:

{'nova_object.name': 'Instance', 'nova_object.namespace': 'nova','nova_object.version': '2.7', 'nova_object.data':{Instance实例中的数据},
'nova_object.changes': ['flavor', 'task_state', 'power_state', 'info_cache'……]}

消息反序列化

作为服务端,当接收到client端发送来的消息之后,就会将字典类型的消息转化成能够在服务中相对应的实例对象,调用的方法如下:

oslo_messaging.rpc.client._BaseCallContext.call
--> nova.objects.base.NovaObjectSerializer.deserialize_entity

同时消息通过RPC call请求返回之后,也会经过deserialize_entity函数的处理。在这个函数中会将所有的字典都变为对象的形式。

[{'info_cache': InstanceInfoCache(created_at=2022-09-16T08:19:45Z,deleted=False,deleted_at=None,instance_uuid=10032782-3c3a-4e75-88c0-6b11b36f8072,
network_info=NetworkModel(2774d9d6-9e6c-470d-bdb5-a05a375e368f),updated_at=2022-09-21T08:25:44Z),
'security_groups': SecurityGroupList(objects=[]),
'flavor': Flavor(created_at=2022-08-26T09:16:12Z,deleted=False,deleted_at=None,description=None,disabled=False,ephemeral_gb=0,extra_specs={:architecture='x86_architecture',:category='general_purpose'},flavorid='e3c20f1b-2dba-49d5-9ea6-e9e58f913d09',id=3,is_public=True,memory_mb=1024,name='mini',projects=<?>,root_gb=0,rxtx_factor=1.0,swap=0,updated_at=None,vcpu_weight=0,vcpus=1),
'updated_at': '2022-09-27T08:44:11Z',
'obj_what_changed': ['flavor']}, None]

上述就是在Conductor服务中调用Instance.save之后的消息经过反序列化得到的对象。这些对象最后在oslo_versionedobjects.base.remotable函数中被重新更新到Instance对象中,就此完成数据库的更改。

conductor与数据库交互

在conductor服务中调用的方法是:

nova.conductor.manager.ConductorManager.object_action

直接调用nova.conductor.manager.ConductorManager._object_dispatch完成instance.save方法。然后将内容返回。访问数据库的接口位于nova/db/api.py文件中,该模块只是一个代理,剩下的实现是IMPL,其赋值如下:

_BACKEND_MAPPING = {'sqlalchemy': 'nova.db.sqlalchemy.api'}
IMPL = concurrency.TpoolDbapiWrapper(CONF, backend_mapping=_BACKEND_MAPPING)

Instance类对象与ComputeManager类对象

Instance对象和nova.compute.manager.ComputeManager类对象之间是什么样的关系?也就是说,compute作为服务端,client端将instance的序列化消息传入,然后server端反序列化得到Instance对象,接着compute进程就可以对该Instance对象实例进行相应的操作了。

原因是nova.compute.manager.ComputeManager对象和nova.objects.instance.Instance对象在接收到消息时,作为oslo_messaging.rpc.dispatcher.RPCDispatcher对象的成员变量,直接调用ComputeManager中的方法,并将Instance作为参数传入,这样在ComputeManager对象中就可以直接调用Instance对象了。

compute服务的worker数量

即:同一个节点上有多少个服务在监听compute.control01这个队列,消息在排队,rabbitmq是如何将消息分发到不同的worker线程上的?

注:nova-compute只有一个worker,因为还涉及到与libvirt后端连接,因此只有一个进程监听rabbitmq队列。

而conductor中有多个worker,每个worker都会监听对应的队列:

对于compute服务而言,首先在nova.cmd.compute.main函数中创建nova.service.Service对象实例,然后通过oslo_service.service.ServiceLauncher对象继续调用oslo_service.service.Services.run_service,在进程中调用nova.service.Service.start函数。

调用nova.rpc.get_server创建RPC Consumer所需的队列等信息。

等接收到消息之后,会将消息转换成实例对象,并调用ComputeManager对象中的类方法对参数进行处理。


Compute通过Conductor访问数据库方法相关推荐

  1. python获取mysql中的数据供js调用_详解js文件通过python访问数据库方法

    我来教你 js文件怎么通过python访问数据库,希望能够为你带来帮助. 1.如果是要提交表单内容给 服务器的 python 处理,那么只需要在表单 里面的 action 填写服务端的处理路由就可以了 ...

  2. jdbc访问数据库方法executeQuery、executeUpdate 和 execute

    executeQuery.executeUpdate 和 execute返回值 Statement 接口提供了三种执行 SQL 语句的方法:executeQuery.executeUpdate 和 e ...

  3. Spring访问数据库异常的处理方法(转)

    原文链接:http://sarin.javaeye.com/blog/888458 今天我们将谈谈Spring访问数据库异常的处理方法,使用JDBC API时,很多操作都要声明抛出java.sql.S ...

  4. 用Mysql网页式管理工具安全地访问数据库的方法

    2019独角兽企业重金招聘Python工程师标准>>> 用Mysql网页式管理工具安全地访问数据库的方法 在使用通达OA系统时很多用户需要借助Mysql网页式管理工具进入后台数据库去 ...

  5. Mybatis源码分析之(四)mapper访问数据库的底层原理(代理方法中具体访问数据库的细节)

    从之前的文章,我们知道了其实mapper真正执行的方法就下面的最后两行.(以下所有的分析都基于一次mybatis的一次select查询. MapperProxy类中的invoke函数 public O ...

  6. python数据库实体_python---使用get方法访问‘数据库’实体

    使用get方法访问'数据库'实体 #simple database #people people = { 'Alice':{ 'phone':'2341', 'addr':'Foo drive 23' ...

  7. 无法用ip连接mysql数据库_MYSQL数据库无法使用IP访问的方法

    MYSQL数据库无法使用IP访问的方法 Windows下面首先要保证防火墙例外中含有mysql的端口如3306 PHP+mysql的时候发现连接数据库只能使用localhost,但是使用IP就不能连接 ...

  8. jython mysql_jython 访问数据库的方法

    jython 访问数据库 基本上有2个方法, 使用 zxJDBC (符合Python DB API2.0规范), 或者直接使用JDBC. 先写点dbexts, dbexts是zxJDBC作者写的一个扩 ...

  9. matlab如何连接数据库,matlab访问数据库的几种方法

    matlab访问数据库的几种方法 一.通过MATLAB 提供的数据库引擎, 以下是MATLAB ,DATABASE TOOLBOX中的例子, 通过ODBC/JDBC 接口访问具体的数据库 functi ...

最新文章

  1. CSS实现不固定宽度和高度的自动居中
  2. Vue.set()实现数据动态响应
  3. 基于nonebot的QQ群聊机器人制作(一)
  4. adb 切换usb模式_如何用adb打开usb调试
  5. 学习 MySQL 需要知道的 28 个小技巧
  6. discuz论坛模板文件目录
  7. channel java_Java Channel
  8. java实现gdal栅格矢量化_gdal栅格矢量化 - osc_lfs4vsih的个人空间 - OSCHINA - 中文开源技术交流社区...
  9. 硬件工程师的你也不想一辈子画图、调板子吧!!!
  10. 【Unity】关于U3d与bip骨骼适配
  11. Ubuntu 16.04 安装显卡驱动(详细!)
  12. ppt计算机网络技术,计算机网络技术.ppt
  13. 【GIS | WebGis的对比】Webgis地图框架的对比
  14. [HAL]STM32 SPI+DMA驱动WS2812
  15. 1.GraspNet-API之Grasp Lable Format
  16. zynq linux如何使用pl ip,ZYNQ+linux网口调试笔记(3)PL-ETH
  17. MySQL必知必会学习历程(一)
  18. win10局域网中只能发现部分计算机,Windows10系统局域网中共享计算机找不到怎么办...
  19. 一篇文章带你学会 Spring 中的 JdbcTemplate 增删改查操作
  20. [笔记分享] [SCons] SCons工具之Manipulation

热门文章

  1. 未来集市未来怎么样_大流行后的未来
  2. WebSocket集群解决方案
  3. 超级网管员——网络管理
  4. ASP.NET 生成二维码(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
  5. 创业项目管理与孵化平台
  6. 直击进博会 | SSAB、依维柯、3M、拜耳、辉瑞、罗氏、麦当劳、宝洁等展示最新成果...
  7. 服务器硬件维修常用问题,服务器CPU与内存常见故障及处理方法
  8. 云办公系统 skyeye v3.1.5 发布
  9. 魔兽中各族单位名称英文缩写
  10. Winform控件开发(11)——numericUpDown(史上最全)