首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 服务器 > 云计算 >

Glance源码架构探秘(3)

2013-03-13 
Glance源码架构探秘(三)Glance源码架构探秘(一)Glance源码架构探秘(二)Glance源码架构探秘(三)上一章我们

Glance源码架构探秘(三)

Glance源码架构探秘(一)

Glance源码架构探秘(二)

Glance源码架构探秘(三)


上一章我们分析了OpenStack中如何用eventlet库创建一个“绿化”的协程式web server,以及WSGI相关概念及在Python中的参考实现,本章我们将具体地讲解WSGI程序内部的框架。

其实,简单的说,Glance及其他OpenStack的组件和大多数的web service一样,也是实现了一个MVC的框架的(关于MVC框架的概念,并不是本文的重点,可自行展开阅读),这个框架称之为RackSpace框架。包括消息路由,控制器Controller、action等等。

这个框架并非完全自己实现,而是借用了许多开源的组件,比如消息路由就用到了Routes这个组件。Routes是借鉴了ruby on rails的某些思想后在Python上的一个实现,用于路由URL消息至对应的控制器和动作action,也可以用来生成URLs。

Routes用法非常清晰明了

>>> from webob import >>> = 'wsgi.url_scheme''http'...>>> = >>> = .'/article?id=1'>>> from pprint import >>> .{'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/article', 'QUERY_STRING': 'id=1', 'REQUEST_METHOD': 'GET', 'SCRIPT_NAME': '', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': 'HTTP/1.0', 'wsgi.errors': <open file '<stderr>', mode 'w' at ...>, 'wsgi.input': <...IO... object at ...>, 'wsgi.multiprocess': False, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0)}
上面的示例程序就简单说明了如何用webob的Request生成一个request请求和解析一个request请求的环境信息。

然而,webob的功能不止于此。其还有一个功能就是将一个普通的函数function包装为一个WSGI函数,并符合WSGI函数的规范(实现规范的接口,evn,start_response)。webob.dec.wsgify

class Resource(object):    """    WSGI app that handles (de)serialization and controller dispatch.    Reads routing information supplied by RoutesMiddleware and calls    the requested action method upon its deserializer, controller,    and serializer. Those three objects may implement any of the basic    controller action methods (create, update, show, index, delete)    along with any that may be specified in the api router. A 'default'    method may also be implemented to be used in place of any    non-implemented actions. Deserializer methods must accept a request    argument and return a dictionary. Controller methods must accept a    request argument. Additionally, they must also accept keyword    arguments that represent the keys returned by the Deserializer. They    may raise a webob.exc exception or return a dict, which will be    serialized by requested content type.    """    def __init__(self, controller, deserializer=None, serializer=None):        """        :param controller: object that implement methods created by routes lib        :param deserializer: object that supports webob request deserialization                             through controller-like actions        :param serializer: object that supports webob response serialization                           through controller-like actions        """        self.controller = controller        self.serializer = serializer or JSONResponseSerializer()        self.deserializer = deserializer or JSONRequestDeserializer()    @webob.dec.wsgify(RequestClass=Request)    def __call__(self, request):        """WSGI method that controls (de)serialization and method dispatch."""        action_args = self.get_action_args(request.environ)        action = action_args.pop('action', None)        deserialized_request = self.dispatch(self.deserializer,                                             action, request)        action_args.update(deserialized_request)        action_result = self.dispatch(self.controller, action,                                      request, **action_args)        try:            response = webob.Response(request=request)            self.dispatch(self.serializer, action, response, action_result)            return response        # return unserializable result (typically a webob exc)        except Exception:            return action_result    def dispatch(self, obj, action, *args, **kwargs):        """Find action-specific method on self and call it."""        try:            method = getattr(obj, action)        except AttributeError:            method = getattr(obj, 'default')        return method(*args, **kwargs)    def get_action_args(self, request_environment):        """Parse dictionary created by routes library."""        try:            args = request_environment['wsgiorg.routing_args'][1].copy()        except Exception:            return {}        try:            del args['controller']        except KeyError:            pass        try:            del args['format']        except KeyError:            pass        return args

Resource这个类可以对请求解串行化,或串行化响应信息,并可以分发controller控制器action的方法。这个类的初始化方法会给对象添加三个属性,controller、serializer、deserializer,分别为控制器,串行化,逆串行化。对象函数__call__也被装饰为WSGI函数,接受上一级WSGI函数的请求,并将上一级Routes后的路由信息(controller=?action=?)通过dispatch方法将指定的action分发到controller控制器类所对应的方法,在源码中用到了getattr,动态的获得对象的绑定方法。

通过上述一系列步骤,就将glance命令请求消息经过路由、分发等步骤送到了控制器类所对应的action方法中,让glance得以进一步的执行客户发来的请求命令。前面通过三章的篇幅,为大家讲解了glance/common/wsgi.py这个文件,主要实现了一个web框架的大部分功能。因为OpenStack的组件都是基于同一套rackspace框架的,这对于我们今后学习Nova,Cinder等其他OpenStack都是颇有益处的。所以今后如有Nova等组件的源码探秘,此部分也不再会单独分析,将把经历多投入到其他方面。


后面几章将开始具体分析glance在接到请求命令后,如何进行镜像的上传,下载,更新等,同样包括数据库和镜像元数据更新等的操作,其中用到了许多非常棒的设计模式,敬请期待!






热点排行