WSGI 详解 和中间件的一些内容

WSGI 简介

 

wsgi代码源码详解>>点我

 

介绍

 

要很好地理解下面的代码,最好有一定的 socket 编程基础,了解 socket 的基本概念和流程。

 

wsgiref 是 PEP 333 定义的 wsgi 规范的范例实现,里面的功能包括了:

 

  • 操作 wsgi 的环境变量
  • 应答头部的处理
  • 实现简单的 HTTP server
  • 简单的对程序端和服务器端校验函数

 

我们先看一个简单的代码实例,然后跟着例子去理解源码:

 

app.py

 

 

server.py

 

 

然后执行 python server.py 启动 sever,用 curl 发送一个请求 curl -i http://localhost:8000/,会有以下输出:

 

 

server 的终端会有一条记录:

 

 

如何使用就讲到这里,下面就开始源码之旅吧!

 

源码分析

 

你可以使用 python -c 'import wsgiref; help(wsgiref)' 查看 wsgiref 库的路径和简介等信息,wsgiref 文件夹的结构如下:

 

 

主要的代码结构如下图所示:

 

 

simple_server.py

 

我们先看一下 make_server 是怎么启动一个 wsgi 服务器的:

 

 

这个函数做的事情就是:监听在本地的端口上,接受来自客户端的请求,通过 WSGIServer 和 WSGIRequestHandler 处理后,把请求交给程序的的可调用对象 app,然后返回 app 的结果给客户端。

 

这里有两个重要的类:WSGIServer 和 WSGIRequestHandler。下面分别看一下它们的代码和执行的功能。

 

 

WSGIServer 在原来的 HTTPServer 上面封装了一层,在原来的 HTTPServer 的基础上又额外做了下面的事情:

 

  • 覆写原来的 server_bind 函数,添加初始化 environ 变量的动作
  • 添加了处理满足 wsgi 的 app 函数:set_app 和 get_app

 

然后看另外一个类 WSGIRequestHandler:

 

 

这个类从名字就能知道它的功能——处理客户端的 HTTP 请求,它也是在原来处理 http 请求的BaseHTTPRequestHandler 类上添加了 wsgi 规范相关的内容。

 

  • get_environ: 解析 environ 变量
  • handle: 处理请求,把封装的环境变量交给 ServerHandler,然后由 ServerHandler 调用 wsgi app,ServerHandler 类会在下面介绍。

 

handler.py

 

这个文件主要是 wsgi server 的处理过程,定义 start_response、调用 wsgi app 、处理 content-length 等等。

 

可以参考这篇文章里的 wsgi server 的简单实现。

 

 

一条 HTTP 请求的旅程

 

服务器端启动服务,等到客户端输入 curl -i http://localhost:8000/ 命令,摁下回车键,看到终端上的输出,整个过程中,wsgi 的服务器端发生了什么呢?

 

  1. 服务器程序创建 socket,并监听在特定的端口,等待客户端的连接
  2. 客户端发送 http 请求
  3. socket server 读取请求的数据,交给 http server
  4. http server 根据 http 的规范解析请求,然后把请求交给 WSGIServer
  5. WSGIServer 把客户端的信息存放在 environ 变量里,然后交给绑定的 handler 处理请求
  6. HTTPHandler 解析请求,把 method、path 等放在 environ,然后 WSGIRequestHandler 把服务器端的信息也放到 environ 里
  7. WSGIRequestHandler 调用绑定的 wsgi ServerHandler,把上面包含了服务器信息,客户端信息,本次请求信息得 environ 传递过去
  8. wsgi ServerHandler 调用注册的 wsgi app,把 environ 和 start_response 传递过去
  9. wsgi app 将reponse header、status、body 回传给 wsgi handler
  10. 然后 handler 逐层传递,最后把这些信息通过 socket 发送到客户端
  11. 客户端的程序接到应答,解析应答,并把结果打印出来。

 

 

背景

Python Web 开发中,服务端程序可以分为两个部分,一是服务器程序,二是应用程序前者负责把客户端请求接收,整理,后者负责具体的逻辑处理为了方便应用程序的开发,我们把常用的功能封装起来,成为各种Web开发框架,例如 Django, Flask, Tornado。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器

Python Web开发中,这个标准就是 The Web Server Gateway Interface, 即 WSGI. 这个标准在PEP 333中描述,后来,为了支持 Python 3.x, 并且修正一些问题,新的版本在PEP 3333中描述。

WSGI 是什么

WSGI 是服务器程序与应用程序的一个约定,它规定了双方各自需要实现什么接口,提供什么功能,以便二者能够配合使用

WSGI 不能规定的太复杂,否则对已有的服务器来说,实现起来会困难,不利于WSGI的普及。同时WSGI也不能规定的太多,例如cookie处理就没有在WSGI中规定,这是为了给框架最大的灵活性。要知道WSGI最终的目的是为了方便服务器与应用程序配合使用,而不是成为一个Web框架的标准。

另一方面,WSGI需要使得middleware(是中间件么?)易于实现。middleware处于服务器程序与应用程序之间,对服务器程序来说,它相当于应用程序,对应用程序来说,它相当于服务器程序。这样,对用户请求的处理,可以变成多个 middleware 叠加在一起,每个middleware实现不同的功能。请求从服务器来的时候,依次通过middleware,响应从应用程序返回的时候,反向通过层层middleware。我们可以方便地添加,替换middleware,以便对用户请求作出不同的处理。

WSGI 内容概要

WSGI主要是对应用程序与服务器端的一些规定,所以,它的主要内容就分为两个部分。

应用程序

WSGI规定:

1. 应用程序需要是一个可调用的对象

在Python中:

  • 可以是函数
  • 可以是一个实例,它的类实现了__call__方法
  • 可以是一个类,这时候,用这个类生成实例的过程就相当于调用这个类

同时,WSGI规定:

2. 可调用对象接收两个参数

这样,如果这个对象是函数的话,它看起来要是这个样子:

# callable function
def application(environ, start_response):
    pass

如果这个对象是一个类的话,它看起来是这个样子:

# callable class
class Application:
    def __init__(self, environ, start_response):
        pass

如果这个对象是一个类的实例,那么,这个类看起来是这个样子:

# callable object
class ApplicationObj:
    def __call__(self, environ, start_response):
        pass

最后,WSGI还规定:

3.可调用对象要返回一个值,这个值是可迭代的。

 

middleware

另外,有些功能可能介于服务器程序和应用程序之间,例如,服务器拿到了客户端请求的URL, 不同的URL需要交由不同的函数处理,这个功能叫做 URL Routing,这个功能就可以放在二者中间实现,这个中间层就是 middleware。

middleware对服务器程序和应用是透明的,也就是说,服务器程序以为它就是应用程序,而应用程序以为它就是服务器。这就告诉我们,middleware需要把自己伪装成一个服务器,接受应用程序,调用它,同时middleware还需要把自己伪装成一个应用程序,传给服务器程序。

其实无论是服务器程序,middleware 还是应用程序,都在服务端,为客户端提供服务,之所以把他们抽象成不同层,就是为了控制复杂度,使得每一次都不太复杂,各司其职。

 

posted on 2018-03-02 16:08  王大拿  阅读(2264)  评论(0编辑  收藏  举报

导航