我们常说“服务器”,实际上服务器是一个很宽泛的概念。
服务器包括服务器硬件、服务器程序、以及部署在服务器上的应用程序。
服务器硬件:也称伺服器,是提供计算服务的硬件设备,包括处理器、硬盘、内存、系统总线等。
服务器软件:光有服务器硬件是无法提供服务的,至少需要有运行于服务器之上的操作系统、数据库软件、以及提供部署功能的web容器等程序。这些软件与服务器硬件一起,共同组成了我们概念中的“服务器”。
应用程序(后台程序):应用程序是运行在服务器上,处理请求并返回响应的程序,我们日常所说的“web开发”、“后台开发”做的就是web应用程序的开发工作。一般,web应用程序需要部署于web容器中,并且与数据库产生数据交互。三者关系大概为:web容器负责实现一些通信协议,并且监听服务器硬件的网关、端口,接收请求,并转发给web应用程序;web应用程序接收请求,提取请求相关信息与参数,调用中间件或者自身实现的业务逻辑(此过程或许会与数据库产生数据交互),并将处理结果以http响应的形式返回给web容器;web容器再将接收到的响应返回给浏览器进行显示。
在上面的过程中,提及到了 web容器 与 应用程序 之间的请求转发和响应通信,那么问题来了:web容器 有 Apahce、Nginx、Gunicorn等多种选择,而 应用程序 也可能选用Flask、Django等等各种框架进行开发,难道我们需要针对不同的容器或开发框架,都自己去实现一遍它们的通信逻辑吗?当然不是。为了建立起web容器与应用程序之间的通信规范,于是有了我们所说的——WSGI,Web Server Gateway Interface,Python Web 服务器网关接口。
PythonWeb服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是一个协议,是 Python应用程序或框架 与 Web容器 之间的一种接口规范。
只要双方都按照这个规范,分别去实现自己需要做的事,那么二者就可以顺利地进行通信。
WSGI
协议主要包括server
和application
两部分。
WSGI server接口
负责从客户端接收请求,将request
转发给application
,并将application
返回的response
返回给客户端。
我们常用的web容器,如Apahce、Nginx、Gunicorn等都实现了这个接口。
接口实现方式:
def run(application): #服务器程序调用应用程序实例
environ = {} #设定参数
def start_response(xxx): #设定参数
pass
result = application(environ, start_response) #调用应用程序实例的__call__函数
def write(data):
pass
def data in result: #迭代访问
write(data)
服务器程序主要做了以下的事:
1. 设定应用程序所需要的参数
2. 调用应用程序
3. 迭代访问应用程序的返回结果,并传给客户端
WSGI application接口
接收由server
转发过来的request
,处理请求,并将处理结果返回给server
。
接口的实现方式:
这个对象接收两个参数
从源码中,我们可以看到,这两个参数是environ, start_response. 以可调用对象为一个类为例:
class application:
def __call__(self, environ, start_response):
pass
可调用对象需要返回一个可迭代的值。以可调用对象为一个类为例:
class application:
def __call__(self, environ, start_response):
return [xxx]
middleware是介于服务器程序和应用程序中间的部分,middleware对于服务器程序(web容器)和应用程序来说都是透明的:对服务器程序来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器程序。
因此,中间件程序需要同时实现wsgi server与wsgi application接口,可以在WSGI服务器与WSGI应用之间起调节作用。
中间件是一个很强大的领域,相信很多同学都听说或正在担任中间件的开发工作。
我们知道,应用程序主要是做业务逻辑实现的,那么,在请求到达应用程序之前,我们可以用来做些什么呢?一个很简单的场景,就是做请求的预处理或者基本信息提取。
上面提到,WSGI Server调用WSGI Application时,需要两个参数:environ
和start_response,其中,
environ
是一个字典,它来自CGI,详情请看文档:The Common Gateway Interface Specification
文中“Environment variables”,列举了environ字典中包含的信息,主要有:
AUTH_TYPE
CONTENT_LENGTH #HTTP请求中Content-Length的部分
CONTENT_TYPE #HTTP请求中Content-Tpye的部分
GATEWAY_INTERFACE
PATH_INFO #URL路径除了起始部分后的剩余部分,用于找到相应的应用程序对象,如果请求的路径就是根路径,这个值为空字符串
PATH_TRANSLATED
QUERY_STRING #URL路径中?后面的部分
REMOTE_ADDR
REMOTE_HOST
REMOTE_IDENT
REMOTE_USER
REQUEST_METHOD #HTTP 请求方法,例如 "GET", "POST"
SCRIPT_NAME #URL路径的起始部分对应的应用程序对象,如果应用程序对象对应服务器的根,那么这个值可以为空字符串
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL #客户端请求的协议(HTTP/1.1 HTTP/1.0)
SERVER_SOFTWARE
以及客户端发起HTTP时所携带过来的一些关于客户端的信息:
HTTP_HOST = 客户端host
HTTP_ACCEPT = ‘text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8‘
HTTP_ACCEPT_ENCODING = ‘gzip,deflate,sdch‘
HTTP_ACCEPT_LANGUAGE = ‘en-US,en;q=0.8,zh;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2‘
HTTP_CONNECTION = ‘keep-alive‘
HTTP_USER_AGENT = 客户端代理信息(浏览器、内核版本等)
WSGI
协议其实是定义了一种server
与application
解耦的规范,即可以有多个实现WSGI server
的服务器,也可以有多个实现WSGI application
的框架,那么就可以选择任意的server
和application
组合实现自己的web
应用。例如uWSGI
和Gunicorn
都是实现了WSGI server
协议的服务器,Django
,Flask
是实现了WSGI application
协议的web
框架,可以根据项目实际情况搭配使用。WSGI
一样是一种通信协议,是uWSGI
服务器的独占协议,用于定义传输信息的类型(type of information
),每一个uwsgi packet
前4byte
为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi
协议的10倍快。 uWSGI
旨在为部署分布式集群的网络应用开发一套完整的解决方案。主要面向web
及其标准服务。由于其可扩展性,能够被无限制的扩展用来支持更多平台和语言。uWSGI
是一个web
服务器,实现了WSGI
协议,uwsgi
协议,http
协议等。uWSGI
的主要特点是:
app
管理app
的性能和瓶颈)uWSGI
服务器自己实现了基于uwsgi
协议的server
部分,我们只需要在uwsgi
的配置文件中指定application
的地址,uWSGI
就能直接和应用框架中的WSGI application
通信。
原文:https://www.cnblogs.com/ygj0930/p/10826084.html