xioaxu790 发表于 2014-12-22 20:56:49

Glance 源码分析(3) – WSGI 框架

问题导读
1、什么是WSGI 框架?
2、OpenStack 大多数模块采用了怎样的方法来作为一个 HTTP RestFul API Server?
3、什么是工厂函数?

static/image/hrline/4.gif




Table of Contents

[*]Server
[*]paste 的工厂函数



Server
OpenStack 大多数模块封装了 eventlet 以及 eventlet.wsgi.server 组成一个 class Server 来作为一个 HTTP RestFul API Server. 咋一看他的封装好像很复杂, 但是如果了解 eventlet 的基本概念, 这部分代码其实非常简单.

eventlet 在它内部定义的 greenthread(绿色线程) 里, 它利用协程来实现并发. 协程的介绍可以看我以前写的文章: Coroutine(协程) 介绍

为了彻底实现高性能的 I/O 并发, eventlet 甚至把底层的一些 API 都做了修改, .e.g socket, listen. 更多的 eventlet 的内容不在这讨论, 可以去 官网查看相关的文档

下面是一个简单的小例子利用 eventlet 构建一个 HTTP Server, 基本上就是 glance 的 class Server 的核心骨架:
class APP(object):
    @webob.dec.wsgify
    def __call__(self, req):
      return 'hello world'

# 创建一个绑定在本机 8000 端口 的 socket.
sock = eventlet.listen(('0.0.0.0', 8000))
# 启动 wsgi server
eventlet.wsgi.server(sock, APP())


that’s it, so easy. 把他保存到文件并运行, 就是一个简单的 Http server, 并且 我可以付责任的告诉你, openstack 中的 WSGI 服务就是这么运行的.

所以我们回过头看 glance.common.wsgi.py:Server 这个类, 它只不过包装了一下 eventlet 的参数, 并且 WSGI 实例是在子进程里面运行的, 支持多进程运行该服务(多核考虑), 对外提供了 Server:start() 和 Server:wait() 两个 API, 其他的, 就真没什么了.

paste 的工厂函数
请先复习一下 paste的相关内容. 然后看下面的图:



图中每一个 filter 都对应着一个工厂函数(可调用的实例), 比如:

paste.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory

对应的实例都是 Middleware 其实是的子类, 前面我们讲过, paste配置里面的工厂函数 所创造的是一个能调用的实例(包含__call__方法), 当收到用户请求的时候就会自动调用该 实例, 也就是调用 __call__ 方法. 这里 openstack 所有模块抽象除了一个类 Middleware, 封装了 process_request 方法. 每个 filter 子类只需要继承 该类, 如果需要做处理, 就覆盖 process_request 方法, 然后 Middleware 里面 的 __call__ 方法会根据 process_request 的返回值来判断是否交给下一个 filter 处理.
# file: glance/api/middleware/version_negotiation.py
class VersionNegotiationFilter(wsgi.Middleware):


class Middleware(object):
    def __init__(self, application):
      self.application = application

    @classmethod
    def factory(cls, global_conf, **local_conf):
      def filter(app):
            return cls(app)
      return filter

    def process_request(self, req):
      return None

    def process_response(self, response):
      return response

    @webob.dec.wsgify
    def __call__(self, req):
      # 首先调用子类的 process_request 方法, 如果子类没有实现这个方法或者
      # 返回值不为空, 那么直接将子类的返回回复给用户, 否则进行下一个 filter
      # 的处理. 这其实是一个递归的过程, 最后返回从下游(filter或app)的到的返回
      # 给用户
      response = self.process_request(req)
      if response:
            return response
      response = req.get_response(self.application)
      response.request = req
      try:
            return self.process_response(response)
      except webob.exc.HTTPException as e:
            return e



355815741 发表于 2014-12-23 09:04:00

好东西,学习学习,谢谢分享~

eason 发表于 2015-7-9 14:55:03

期待楼主更多后续文章
页: [1]
查看完整版本: Glance 源码分析(3) – WSGI 框架