发布网友 发布时间:2022-04-24 14:51
共2个回答
懂视网 时间:2022-04-11 09:13
base.remotable_classmethod 2 base.remotable 3 staticmethod 4 db_api.api_context_manager.reader 5 db_api.api_context_manager.writer 6 property 7 db_api.pick_context_manager_reader 8 db_api.pick_context_manager_writer 9 base.NovaObjectRegistry.register 10 require_context View Code
参考:https://blog.csdn.net/tiantao2012/article/details/78530213
测试:
1.使用remotable_classmethod
我们看一下remotable_classmethod这个装饰器的定义:
1 from oslo_versionedobjects import base as ovoo_base 2 remotable_classmethod = ovoo_base.remotable_classmethod 3 4 def remotable_classmethod(fn): 5 """Decorator for remotable classmethods.""" 6 @six.wraps(fn) 7 def wrapper(cls, context, *args, **kwargs): 8 if cls.indirection_api: 9 version_manifest = obj_tree_get_versions(cls.obj_name()) 10 try: 11 result = cls.indirection_api.object_class_action_versions( 12 context, cls.obj_name(), fn.__name__, version_manifest, 13 args, kwargs) 14 except NotImplementedError: 15 # FIXME(danms): Maybe start to warn here about deprecation? 16 result = cls.indirection_api.object_class_action( 17 context, cls.obj_name(), fn.__name__, cls.VERSION, 18 args, kwargs) 19 else: 20 result = fn(cls, context, *args, **kwargs) 21 if isinstance(result, VersionedObject): 22 result._context = context 23 return result 24 25 # NOTE(danms): Make this discoverable 26 wrapper.remotable = True 27 wrapper.original_fn = fn 28 return classmethod(wrapper)View Code
这里,如果cls.indirection_api为空,则直接调用fn方法,fn这里一般指数据库的操作方法。
如果cls.indirection_api不为空,则调用cls.indirection_api中的object_class_action_versions方法。
我们搜索一下nova中关于indirection_api的初始化相关的代码:
[root@controller nova]# grep -rn indirection_api cmd/api_metadata.py:45: objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI() cmd/dhcpbridge.py:120: objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI() cmd/compute.py:54: objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI() cmd/network.py:54: objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()View Code
而这里的conductor_rpcapi指的就是nova.conductor中的rpcapi。
我们知道nova-conductor的rpcapi用的是rabbitmq做连接的,分析如下:
1 @profiler.trace_cls("rpc") 2 class ConductorAPI(object): 3 def __init__(self): 4 super(ConductorAPI, self).__init__() 5 ...... 6 self.client = rpc.get_client(target, 7 version_cap=version_cap, 8 serializer=serializer)View Code
在get_client 中,初始化了一个RPCClient对象:
1 def get_client(target, version_cap=None, serializer=None): 2 assert TRANSPORT is not None 3 4 if profiler: 5 serializer = ProfilerRequestContextSerializer(serializer) 6 else: 7 serializer = RequestContextSerializer(serializer) 8 9 return messaging.RPCClient(TRANSPORT, 10 target, 11 version_cap=version_cap, 12 serializer=serializer)View Code
这里用assert声明了TRANSPORT这个变量不为空,那么这个变量是在哪里初始化的呢?
在nova.conductor.rpc.py中的init方法里面,对其进行了初始化:
1 def init(conf): 2 global TRANSPORT, NOTIFICATION_TRANSPORT, LEGACY_NOTIFIER, NOTIFIER 3 exmods = get_allowed_exmods() 4 TRANSPORT = create_transport(get_transport_url())View Code
而这个方法是在nova.config.py中初始化的:
1 def parse_args(argv, default_config_files=None, configure_db=True, 2 init_rpc=True): 3 ...... 4 if init_rpc: 5 rpc.init(CONF)View Code
parse_args这个方法又在nova的每个服务初始化的时候就定义了:
从上面我们可以得知,一般是nova-compute和nova-network服务,其对应的cls.indirection_api不为空,所以读写数据库都是通过nova-conductor,也就是rabbitmq来完成的。
从remotable_classmethod的定义来看,对数据库的操作都是调用 cls.indirection_api中的object_class_action_versions方法来实现的。这个方法在nova-conductor的rpcapi里面实现的。
1 def object_class_action_versions(self, context, objname, objmethod, 2 object_versions, args, kwargs): 3 cctxt = self.client.prepare() 4 return cctxt.call(context, ‘object_class_action_versions‘, 5 objname=objname, objmethod=objmethod, 6 object_versions=object_versions, 7 args=args, kwargs=kwargs)View Code
根据RPC的调用原理,这里调用的是nova.conductor.manager 中的 object_class_action_versions 方法。
这个方法定义如:
1 def object_class_action_versions(self, context, objname, objmethod, 2 object_versions, args, kwargs): 3 objclass = nova_object.NovaObject.obj_class_from_name( 4 objname, object_versions[objname]) 5 args = tuple([context] + list(args)) 6 result = self._object_dispatch(objclass, objmethod, args, kwargs)View Code
因此,可以得知,最终的结果是通过self._object_dispatch来实现的。
self._object_dispatch的定义如:
1 def _object_dispatch(self, target, method, args, kwargs): 2 try: 3 return getattr(target, method)(*args, **kwargs) 4 except Exception: 5 raise messaging.ExpectedException()View Code
这里的target就是对应的object对象,method就是对应的object方法。
又由于nova-conductor对应的self.indirection_api为空,因此,这里直接调用了数据库的操作方法来返回结果。
测试在nova boot实例的过程中,nova-compute在操作数据库过程所消耗的时间:
测试 instance.save()
使用remotable:
1 cmd/compute.py: 2 cmd_common.block_db_access(‘nova-compute‘) 3 objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()View Code
数据库访问次数->消耗时间(s):
1-> 0.119282 10->0.704272 100-> 8.679072 1000-> 59.863044 10000-> 312.080721 100000->3140.704155View Code
不使用remotable:
1 cmd/compute.py: 2 #cmd_common.block_db_access(‘nova-compute‘) 3 #objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()View Code
数据库访问次数->消耗时间(s):
1->0.076283 10->0.153130 100->1.267794 1000->10.103049 10000->105.528138 100000->1027.132933View Code
因此,通过conductor操作数据库的时间比直接操作数据库的时间要更长,在数据库调用次数越大的情况下越明显。
Nova-compute数据库读写测试
标签:config style view result 搜索 ble sel mes comm
热心网友 时间:2022-04-11 06:21
nova这一组件包含了许多的小组件,其中有API Server (nova-api)、Message Queue (rabbit-mq server)、Compute Workers (nova-compute)、Network Controller (nova-network)、Scheler (nova-scheler)、Conctor(nova-conctor)。
nova-api是一个交互接口,管理者可以通过这个接口来管理内部基础设施,也可以通过这个接口向用户提供服务。当然基于web的管理也是通过这个接口,然后向消息队列发送消息,达到资源调度的功能。
OpenStack 包含两个主要模块:Nova 和 Swift,前者是 NASA 开发的虚拟服务器部署和业务计算模块;后者是 Rackspace开发的分布式云存储模块,两者可以一起用,也可以分开单独用。Nova是最核心的,一套虚拟化管理程序,可管理网络和存储。
Rabbit-mq server是计算资源中的一个消息队列,为各个组件传达消息实现资源调度。nova-compute是用于处理管理实例生命周期。通过消息队列接收请求,并承担操作工作。
nova-network相当于云计算系统内部的一个路由器,他承担了IP地址的划分以及配置VLAN和安全组的划分。
nova-scheler是一个拥有把nova-API调用映射为Open Stack功能的组件,会根据诸如CPU构架、可用域的物理距离、内存、负载等作出调度决定。nova-conctor负责数据库的访问权限控制,避免nova-compute直接访问数据库。
以上内容参考 百度百科--nova