Nova-conductor and amqp (2)

Source: Internet
Author: User

Source code version: Version H

References:

Http://bingotree.cn /? P = 242

Http://blog.csdn.net/gaoxingnengjisuan/article/details/12231633

1. First, check the service startup script.

/Usr/bin/NOVA-Conductor

import sysfrom nova.cmd.conductor import mainif __name__ == "__main__":    sys.exit(main())

Nova/CMD/conductor. py

def main():    ...    server = service.Service.create(binary=‘nova-conductor‘,                                    topic=CONF.conductor.topic,                                    manager=CONF.conductor.manager)    service.serve(server, workers=CONF.conductor.workers)    service.wait()

 

Ii. Analysis of RPC service creation

Nova/service. py

Service Class: @ classmethoddef create (CLS, host = none, binary = none, topic = none, Manager = none, report_interval = none, periodic_enable = none, periodic_fuzzy_delay = none, periodic_interval_max = none, db_allowed = true ):... service_obj = Cls (host, binary, topic, Manager, report_interval = report_interval, periodic_enable = periodic_enable, priority = enabled, priority = enabled, db_allowed = db_allowed) return service_obj

 

Iii. Analysis Service Operation

Nova/service. py

Def serve (server, workers = none): Global _ launcher if _ Launcher: Raise runtimeerror (_ ('serve () can only be called once ')) "service is Nova. openstack. common. service "" _ launcher = service. launch (server, workers = workers)

Nova/openstack/common/service. py

def launch(service, workers=None):    if workers:        launcher = ProcessLauncher()        launcher.launch_service(service, workers=workers)    else:        launcher = ServiceLauncher()        launcher.launch_service(service)    return launcher

Refer to the Service Startup Process (http://www.cnblogs.com/littlebugfish/p/4022907.html) of the Nova-API, that is, starting the coroutine (using eventlet) to run the service, primarily the start function. Note: If you specify multiple workers in the configuration file, multiple processes will listen to the message queue, and the process that obtains the message is responsible for processing. Next, let's look at the code of the Start function, as shown below:

Nova/service. py

Service Class: def start (Self ):... self. manager. pre_start_hook () If self. backdoor_port is not none: Self. manager. backdoor_port = self. backdoor_port "creates amqp connections to facilitate the creation of consumer" "self. conn = RPC. create_connection (New = true) log. debug (_ ("creating consumer connection for service % s") % self. topic) rpc_dispatcher = self. manager. create_rpc_dispatcher (self. backdoor_port) self. conn. create_consumer (self. topic, rpc_dispatcher, fanout = false) node_topic = '% S. % s' % (self. topic, self. host) self. conn. create_consumer (node_topic, rpc_dispatcher, fanout = false) self. conn. create_consumer (self. topic, rpc_dispatcher, fanout = true) self. conn. consume_in_thread () self. manager. post_start_hook () log. debug (_ ("Join ServiceGroup membership for this service % s") % self. topic) self. servicegroup_api.join (self. host, self. topic, self) If self. periodic_enable: If self. periodic_fuzzy_delay: initial_delay = random. randint (0, self. periodic_fuzzy_delay) else: initial_delay = none self. TG. add_dynamic_timer (self. periodic_tasks, initial_delay = initial_delay, periodic_interval_max = self. periodic_interval_max)

Self. Conn. create_consumer (node_topic, rpc_dispatcher, fanout = false ). Self. conn mainly refers to Nova. openstack. common. RPC. impl_qpid.connection (here, the backend Implementation of amqp is qpid, which can be found in Nova. the create_consumer code called is as follows:

def create_consumer(self, topic, proxy, fanout=False):    proxy_cb = rpc_amqp.ProxyCallback(        self.conf, proxy,        rpc_amqp.get_connection_pool(self.conf, Connection))    self.proxy_callbacks.append(proxy_cb)    if fanout:        consumer = FanoutConsumer(self.conf, self.session, topic, proxy_cb)    else:        consumer = TopicConsumer(self.conf, self.session, topic, proxy_cb)    self._register_consumer(consumer)    return consumer

Based on the specific backend amqp implementation, this function will send the queue and exchange creation (the first time it will be created and will be reused later) to the amqp server and bind the request, in this way, the consumer and the specific queue can be bound and monitored. The self. Conn. consume_in_thread function is used to start the consumer thread. It uses evelent. Spawn to create a coroutine to keep running and waiting for the message. A new coroutine will be created to run the remotely called function when the message arrives. When a message arrives in the queue, call proxy_cb for processing, that is, the _ call _ function of the proxycallback object. The Code is as follows:

Nova/openstack/common/rpc/amqp. py

Proxycallback class: def _ call _ (self, message_data): If hasattr (local. store, 'context'): del local. store. context rpc_common. _ safe_log (log. debug, _ ('Received % s'), message_data) self. msg_id_cache.check_duplicate_message (message_data) ctxt = unpack_context (self. conf, message_data) "parse message" "method = message_data.get ('method') ARGs = message_data.get ('args', {}) version = message_data.get ('version ') namespace = message_data.get ('namespace ') if not method: log. warn (_ ('no Method for message: % s') % message_data) ctxt. reply (_ ('no Method for message: % s') % message_data, connection_pool = self. connection_pool) Return "process messages" self. pool. spawn_n (self. _ process_data, ctxt, version, method, namespace, argS) def _ process_data (self, ctxt, version, method, namespace, argS): ctxt. update_store () Try: rval = self. proxy. dispatch (ctxt, version, method, namespace, ** ARGs )...

We can see that the message processing is mainly through the new coroutine (using eventlet) to execute self. _ process_data function, and self. the _ process_data function mainly calls self. proxy. what is the content of the dispatch function?

3.1 first find self. Proxy

According to self. layer-by-layer tracing of the proxy, which is passed in when the above proxycallback is constructed, that is, rpc_dispatcher = self in the Start function. manager. create_rpc_dispatcher (self. backdoor_port), self. when creating the service, the manager has already been set as the conductormanager. The create_rpc_dispatcher Function Code of conductor manager is as follows:

def create_rpc_dispatcher(self, *args, **kwargs):    #self.compute_task_mgr = ComputeTaskManager()    kwargs[‘additional_apis‘] = [self.compute_task_mgr]    return super(ConductorManager, self).create_rpc_dispatcher(*args,            **kwargs)

Based on the class inheritance relationship:

Nova/manager. py

Manager class: def create_rpc_dispatcher (self, backdoor_port = none, additional_apis = none): APIs = [] If additional_apis: APIs. extend (additional_apis) base_rpc = baserpc. baserpcapi (self. SERVICE_NAME, backdoor_port) APIs. extend ([self, base_rpc]) serializer = objects_base.novaobjectserializer () return rpc_dispatcher.rpcdispatcher (APIS, serializer)

Nova/openstack/common/rpc/dispatcher. py

Rpcdispatcher class def _ init _ (self, callbacks, serializer = none): # Callbacks is a list that contains computetaskmanager, conductormanager, and baserpcapi self. callbacks = callbacks if serializer is none: serializer = rpc_serializer.noopserializer () self. serializer = serializer super (rpcdispatcher, self ). _ init __()

Therefore, the final self. Proxy is the rpcdispatcher object. Note that the callbacks attribute of the rpcdispatcher object contains a series of manager classes, which are used to process the method specified in the message. Refer:

 

3.2 analyze the self. Proxy. Dispatch Function

That is, the dispatch function of the rpcdispatcher class. The Code is as follows:

def dispatch(self, ctxt, version, method, namespace, **kwargs):    if not version:        version = ‘1.0‘    had_compatible = False    for proxyobj in self.callbacks:        try:            cb_namespace = proxyobj.RPC_API_NAMESPACE        except AttributeError:            cb_namespace = None        if namespace != cb_namespace:            continue           ...                 if not hasattr(proxyobj, method):            continue        if is_compatible:            kwargs = self._deserialize_args(ctxt, kwargs)            result = getattr(proxyobj, method)(ctxt, **kwargs)            return self.serializer.serialize_entity(ctxt, result)    ...

This function matches the manager according to the namespace, and then analyzes whether the functions in the Manager class match the functions in the message. If they match, the corresponding functions in the Manager class are called for processing. After observation, the rpcapi of components that provide RPC services externally. py and manager. the classes in The py file are matched, and they are matched through the namespace. The names have the same prefix, so if you want to track rpcapi. for subsequent implementation of functions in Py, you only need to view the manager of this component. the corresponding function of the manager class in The py file.

Nova-conductor and amqp (2)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.