WSGI

Author:王蒙
Tags:网络编程
abstract:wsgi 协议是 Application 和 Server 通信的标准接口。要实现 wsgi 的 Application 和 Server 必须遵守 wsgi 协议。遵守这个协议,就可以混合使用各种 wsgi Application 和 wsgi Server。这和让各种牌子的电脑和U盘支持统一的 USB 口,那么任何电脑都可以和任意 U 盘连接是一个道理。

Audience

网络编程

Problem

  • wsgi 的优势
  • wsgi 协议
  • 写 wsgi 的方式
  • wsgi 的常见应用
  • wsgi 与 server 的兼容

Solution

wsgi 的优势

兼容性是 wsgi 的突出优势。 wsgi 接收请求,构造响应,实现了 Application 的处理逻辑。和采用指定 Web Frameworks 方式写 Application 不同,采用 wsgi 协议写的 Application ,可以兼容很多 Server。

wsgi 协议

PEP 3333 详细介绍了 wsgi 协议。

wsgi 协议对于 wsgi Application 的要求:
  • Application 是个 callable 的 object, 函数和类都可以。
  • Application callable 接收两个参数 envrionstart_response
    • environ: environ 包含了 http 请求的所有字段。详细 envrion 中必须包含哪些字段,请查考 PEP 3333
    • start_response: start_response 表示开始返回 response, start_response(status, headers) 接收 status(比如 ‘200 OK’) 和 headers(比如 [‘Content-Type’: 100]), wsgi 在调用 start_response(status, headers) 之后会用 return 或者 yield 把 response 的 body 传递出去。常见 headers 的含义,请参考 http 协议的标准。
  • Application 的返回值是由 bytes 组成的 iterable 的 object。

wsgi 协议对于 Server 的要求:

  • 可以把 Server 想象成之前用 socket 写的服务器,主要负责侦听用户的连接请求。
  • 当有 client 连接到服务器之后,Server 就把请求转成 envrion (附带些 Server 本身提供的信息)传递给 wsgi Application 去处理, wsgi Application 返回的 response 传递给 Server, Server 把这个 response 传递给 client。

写 wsgi 协议的方式

不使用第三方包的方式, 主要分两步:

  • environ 中解析出 http request 中的字段。
  • 根据 http request 的字段,构造 http response。

使用 webob 包:

  • webob 提供了 webob.Requestwebob.Response 方便解析 request 和构造 response。
  • timeapp_webob.py 是使用 webob 定义 wsgi 的例子。

使用 werkzeug 包:

  • 直观的 http 处理逻辑是,收到 http request, 返回 http response。werkzeug 允许我们定义一个接收 request 参数,返回 response 的函数。我们定义的这个函数经 werkzeug.wrappers.Request.application 装饰器装饰,就变成 wsgi。
  • werkzeug 提供的 request 和 response, 要比 wsgi 原生提供的 environ 和 start_response, 方便解析请求和构造响应。
  • timeapp_werkz.py 是使用 werkzeug 定义 wsgi 的例子。

wsgi 写 middleware

request/reponse 在 Server 和 Application 之间传递时,可以通过一个组件处理。这个组件就是中间件。比如 Dispatch 请求的逻辑可以写到中间件了。

wsgi Server

早期 python 性能不行,python 定义的 wsgi application 会装到 Apache Server 上。

后来,出现了一堆 python Server(gunicorn, flask, django 等等), python wsgi 也可以安装到这些 python server 上。gunicorn 运行 wsgi 最为方便。

wsgi 不能兼容到采用异步方式实现的 Server 中,比如 wsgi 和 tornado 不兼容(可以强行让 tornado 使用 wsgi 但是性能会打折扣)。实际上采用异步实现的 Server 兼容性很差,采用了某个异步 Server, 一般也就不得不采用 Server 指定的 Frameworks 去写 Application。

Reference