当前位置: 首页 > 后端技术 > Python

深入理解PythonWSGI

时间:2023-03-26 13:59:15 Python

作为Pythonweb开发者,在程序开发阶段一般不会接触到WSGI这个名词,但是当程序开发完成,考虑上线部署时,WSGI规范是一个绕不开的话题,本文将介绍什么是WSGI。WSGI全拼Web服务器网关接口是为Python语言定义的Web服务器与Web应用程序(或框架)之间的通用编程接口。翻译成大白话,就是说WSGI是一种协议,就像HTTP协议定义了客户端和服务器之间数据传输的规范,WSGI协议定义了Web服务器和Web应用之间协同工作的规范。作为PythonWeb应用程序部署解决方案的Flask或Django等Web框架提供了内置的Web服务器。在本地开发阶段,可以使用flaskrun或pythonmanage.pyrunserver分别启动Flask或Django的内置服务器。在生产环境部署应用时,通常不使用框架内置的Server,而是使用Gunicorn或uWSGI来部署,以获得更好的性能。部署过Pythonweb应用的同学应该对下面的部署架构有所了解,左边是浏览器,右边是服务器。在服务器内部,先通过Nginx监听80/443端口。当收到客户端的请求时,Nginx会将请求转发给监听5000端口的Gunicorn/uWSGIServer,然后通过WSGI协议将请求传递给Flask/Django框架,在框架内部处理请求逻辑后,将以同样的方式返回响应信息。你可能会问,Nginx性能这么高,为什么不直接把应用部署到Nginx上,而是通过中间的Gunicorn/uWSGI做一层转发呢?因为Nginx不遵循WSGI规范,所以不能像Gunicorn/uWSGI那样方便的和Flask/Django框架结合。WSGI规范基于PythonWeb应用程序部署架构,我们知道WSGI位于何??处。接下来我们看看WSGI规范具体定义了什么。就像HTTP协议有客户端和服务器一样,WSGI协议有Application和Server,其中Application指的是Flask、Django等Web框架,Server指的是Gunicorn、uWSGI等Web服务器。WSGI协议规定Application端需要实现为一个可调用对象(函数、类等),其接口如下:defsimple_app(environ,start_response):status='200OK'response_headers=[('Content-type','text/plain')]start_response(status,response_headers)return['Helloworld!\n']simple_app是最简单的Application,它需要接收两个参数,environ是一个dict,里面存储了所有HTTP请求相关信息,由服务器端提供,start_response是一个可调用对象,同样由服务器端提供,simple_app需要在内部调用一次start_response,并将状态码和响应头作为参数传递给它,simple_app最终会返回一个可迭代对象作为HTTPBody的内容返回给客户端。Application端的接口我们已经知道了,我们来看下一个符合WSGI协议的Server端的实现:):print(f'status:{status}')print(f'response_headers:{response_headers}')result=application(environ,start_response)fordatainresult:print(f'response_body:{data}')也是示例函数中在Server端使用,wsgi_server接收一个application作为参数,构造了environ和start_response两个对象,这里使用环境变量信息模拟HTTP请求信息构造environ字典,start_response也定义为一个application函数内部调用,wsgi_server函数最终调用application并打印出来。现在我们有了应用程序端和服务器端,我们可以测试这个简单的WSGI程序示例了。只需将simple_app作为参数传递给wsgi_server并调用wsgi_server:wsgi_server(simple_app)执行上面的代码,会打印如下:status:200OKresponse_headers:[('Content-type','text/plain')]response_body:你好世界!以上,我们分别实现了符合WSGI规范的Application端和Server端。虽然程序看起来比较简单,但是再复杂的PythonWeb框架和Server,也是遵循这个规范的。WSGI的实际应用学习了WSGI规范后,我们就可以验证一下我们平时使用的Pythonweb框架是否真的遵循了这个规范。这里我们以Flask框架的源码为例,可以在https://github.com/pallets/fl...查看Flask的定义:classFlask(Scaffold):...def__call__(self,environ,start_response):"""WSGI服务器调用Flask应用对象作为WSGI应用。这调用:meth:`wsgi_app`,可以包装应用中间件。"""returnself.wsgi_app(environ,start_response)Flask类内部实现了call方法使Flask实例对象成为可调用对象,其接口实现也符合WSGIApplication规范。