Compute通过Conductor访问数据库方法
目录
方法注册
实例序列化与反序列化
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访问数据库方法相关推荐
- python获取mysql中的数据供js调用_详解js文件通过python访问数据库方法
我来教你 js文件怎么通过python访问数据库,希望能够为你带来帮助. 1.如果是要提交表单内容给 服务器的 python 处理,那么只需要在表单 里面的 action 填写服务端的处理路由就可以了 ...
- jdbc访问数据库方法executeQuery、executeUpdate 和 execute
executeQuery.executeUpdate 和 execute返回值 Statement 接口提供了三种执行 SQL 语句的方法:executeQuery.executeUpdate 和 e ...
- Spring访问数据库异常的处理方法(转)
原文链接:http://sarin.javaeye.com/blog/888458 今天我们将谈谈Spring访问数据库异常的处理方法,使用JDBC API时,很多操作都要声明抛出java.sql.S ...
- 用Mysql网页式管理工具安全地访问数据库的方法
2019独角兽企业重金招聘Python工程师标准>>> 用Mysql网页式管理工具安全地访问数据库的方法 在使用通达OA系统时很多用户需要借助Mysql网页式管理工具进入后台数据库去 ...
- Mybatis源码分析之(四)mapper访问数据库的底层原理(代理方法中具体访问数据库的细节)
从之前的文章,我们知道了其实mapper真正执行的方法就下面的最后两行.(以下所有的分析都基于一次mybatis的一次select查询. MapperProxy类中的invoke函数 public O ...
- python数据库实体_python---使用get方法访问‘数据库’实体
使用get方法访问'数据库'实体 #simple database #people people = { 'Alice':{ 'phone':'2341', 'addr':'Foo drive 23' ...
- 无法用ip连接mysql数据库_MYSQL数据库无法使用IP访问的方法
MYSQL数据库无法使用IP访问的方法 Windows下面首先要保证防火墙例外中含有mysql的端口如3306 PHP+mysql的时候发现连接数据库只能使用localhost,但是使用IP就不能连接 ...
- jython mysql_jython 访问数据库的方法
jython 访问数据库 基本上有2个方法, 使用 zxJDBC (符合Python DB API2.0规范), 或者直接使用JDBC. 先写点dbexts, dbexts是zxJDBC作者写的一个扩 ...
- matlab如何连接数据库,matlab访问数据库的几种方法
matlab访问数据库的几种方法 一.通过MATLAB 提供的数据库引擎, 以下是MATLAB ,DATABASE TOOLBOX中的例子, 通过ODBC/JDBC 接口访问具体的数据库 functi ...
最新文章
- CSS实现不固定宽度和高度的自动居中
- Vue.set()实现数据动态响应
- 基于nonebot的QQ群聊机器人制作(一)
- adb 切换usb模式_如何用adb打开usb调试
- 学习 MySQL 需要知道的 28 个小技巧
- discuz论坛模板文件目录
- channel java_Java Channel
- java实现gdal栅格矢量化_gdal栅格矢量化 - osc_lfs4vsih的个人空间 - OSCHINA - 中文开源技术交流社区...
- 硬件工程师的你也不想一辈子画图、调板子吧!!!
- 【Unity】关于U3d与bip骨骼适配
- Ubuntu 16.04 安装显卡驱动(详细!)
- ppt计算机网络技术,计算机网络技术.ppt
- 【GIS | WebGis的对比】Webgis地图框架的对比
- [HAL]STM32 SPI+DMA驱动WS2812
- 1.GraspNet-API之Grasp Lable Format
- zynq linux如何使用pl ip,ZYNQ+linux网口调试笔记(3)PL-ETH
- MySQL必知必会学习历程(一)
- win10局域网中只能发现部分计算机,Windows10系统局域网中共享计算机找不到怎么办...
- 一篇文章带你学会 Spring 中的 JdbcTemplate 增删改查操作
- [笔记分享] [SCons] SCons工具之Manipulation
热门文章
- 未来集市未来怎么样_大流行后的未来
- WebSocket集群解决方案
- 超级网管员——网络管理
- ASP.NET 生成二维码(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
- 创业项目管理与孵化平台
- 直击进博会 | SSAB、依维柯、3M、拜耳、辉瑞、罗氏、麦当劳、宝洁等展示最新成果...
- 服务器硬件维修常用问题,服务器CPU与内存常见故障及处理方法
- 云办公系统 skyeye v3.1.5 发布
- 魔兽中各族单位名称英文缩写
- Winform控件开发(11)——numericUpDown(史上最全)