说说我对 WSGI 的理解
先说下 WSGI 的表面意思,Web Server Gateway Interface 的缩写,即 Web 服务器网关接口。
之前不知道 WSGI 意思的伙伴,看了上面的解释后,我估计也还是不清楚,所以下面结合实际场景说明,先让大家有个大致的认识。最后我们再自己实现一个,加深对 WSGI 的理解。
我们现在使用 Python 编写 Web 应用,可以用比较流行的 Flask、Django 框架,也可以按自己的想法直接写一个。可选的服务器软件也特别多,比如常见的有 Apache、Nginx、IIS 等,除此外,也有很多小众的软件。但是,现在问题来了,我该怎么部署?在没有 WSGI 规范之前,一个服务器调度 Python 应用是用这种方式,另一款服务器使用的是那种方式,这样的话,编写出来的应用部署时只能选择局限的某个或某些服务器,达不到通用的效果。
注意:下文中的代码基于 Python 3.6 编写。
假如有这么一个服务器
wsgi/server.py
# coding=utf-8
import socket
listener = socket.socket()
listener.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
listener.bind(('0.0.0.0', 8080))
listener.listen(1)
print('Serving HTTP on 0.0.0.0 port 8080 ...')
while True:
client_connection, client_address = \
listener.accept()
print(f'Server received connection'
f' from {client_address}')
request = client_connection.recv(1024)
print(f'request we received: {request}')
response = b"""
HTTP/1.1 200 OK
Hello, World!
"""
client_connection.sendall(response)
client_connection.close()
实现比较简单,就是监听 8080 端口,如果有请求在终端进行打印,并返回 Hello, World! 的响应。
终端中启动服务器
➜ wsgi python server.py
Serving HTTP on 0.0.0.0 port 8080 ...
再开一个终端,请求下
➜ ~ curl 127.0.0.1:8080
HTTP/1.1 200 OK
Hello, World!
说明服务器工作正常。
另外有一个 Web 应用
wsgi/app.py
# coding=utf-8
def simple_app():
return b'Hello, World!\r\n'
现在要部署(也就是让这个整体跑起来),简单粗暴的做法就是在服务器里面直接调用 app 中相应的方法。就像这样
wsgi/server2.py
# coding=utf-8
import socket
listener = socket.socket()
listener.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
listener.bind(('0.0.0.0', 8080))
listener.listen(1)
print('Serving HTTP on 0.0.0.0 port 8080 ...')
while True:
client_connection, client_address = \
listener.accept()
print(f'Server received connection'
f' from {client_address}')
request = client_connection.recv(1024)
print(f'request we received: {request}')
from app import simple_app
response = 'HTTP/1.1 200 OK\r\n\r\n'
response = response.encode('utf-8')
response += simple_app()
client_connection.sendall(response)
client_connection.close()
运行脚本
注意:因为使用端口相同的缘故,请先关闭上次的脚本,然后再执行,不然会由于端口冲突而报错。
➜ wsgi python server2.py
Serving HTTP on 0.0.0.0 port 8080 ...
然后请求一下看看效果
➜ ~ curl 127.0.0.1:8080
Hello, World!
嗯,可以了。但是,上面的服务器和应用整体是跑起来了,那么我换一个服务器或者应用呢。由于服务器与应用之间怎么交互完全没有规范,比如服务器应该如何把请求信息传给应用,应用处理完毕后又怎么告诉服务器开始返回响应,如果都是各搞各的,服务器需要定制应用,应用也要定制服务器,这要一个应用能跑起来也太麻烦了点吧。
所以,WSGI 的出现就是为了解决上面的问题,它规定了服务器怎么把请求信息告诉给应用,应用怎么把执行情况回传给服务器,这样的话,服务器与应用都按一个标准办事,只要实现了这个标准,服务器与应用随意搭配就可以,灵活度大大提高。