分享

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

xioaxu790 发表于 2014-12-22 20:56:49 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 2 16954
问题导读
1、什么是WSGI 框架?
2、OpenStack 大多数模块采用了怎样的方法来作为一个 HTTP RestFul API Server?
3、什么是工厂函数?






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 的核心骨架:
  1. class APP(object):
  2.     @webob.dec.wsgify
  3.     def __call__(self, req):
  4.         return 'hello world'
  5. # 创建一个绑定在本机 8000 端口 的 socket.
  6. sock = eventlet.listen(('0.0.0.0', 8000))
  7. # 启动 wsgi server
  8. 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的相关内容. 然后看下面的图:

1.png

图中每一个 filter 都对应着一个工厂函数(可调用的实例), 比如:
  1. [filter:versionnegotiation]
  2. 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 处理.
  1. # file: glance/api/middleware/version_negotiation.py
  2. class VersionNegotiationFilter(wsgi.Middleware):
复制代码


  1. class Middleware(object):
  2.     def __init__(self, application):
  3.         self.application = application
  4.     @classmethod
  5.     def factory(cls, global_conf, **local_conf):
  6.         def filter(app):
  7.             return cls(app)
  8.         return filter
  9.     def process_request(self, req):
  10.         return None
  11.     def process_response(self, response):
  12.         return response
  13.     @webob.dec.wsgify
  14.     def __call__(self, req):
  15.         # 首先调用子类的 process_request 方法, 如果子类没有实现这个方法或者
  16.         # 返回值不为空, 那么直接将子类的返回回复给用户, 否则进行下一个 filter
  17.         # 的处理. 这其实是一个递归的过程, 最后返回从下游(filter或app)的到的返回
  18.         # 给用户
  19.         response = self.process_request(req)
  20.         if response:
  21.             return response
  22.         response = req.get_response(self.application)
  23.         response.request = req
  24.         try:
  25.             return self.process_response(response)
  26.         except webob.exc.HTTPException as e:
  27.             return e
复制代码




已有(2)人评论

跳转到指定楼层
355815741 发表于 2014-12-23 09:04:00
好东西,学习学习,谢谢分享~
回复

使用道具 举报

eason 发表于 2015-7-9 14:55:03
期待楼主更多后续文章
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条