转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826084.html
一:服务器、服务器软件、应用程序(后台)
我们常说“服务器”,实际上服务器是一个很宽泛的概念。
服务器包括服务器硬件、服务器程序、以及部署在服务器上的应用程序。
服务器硬件:也称伺服器,是提供计算服务的硬件设备,包括处理器、硬盘、内存、系统总线等。
服务器软件:光有服务器硬件是无法提供服务的,至少需要有运行于服务器之上的操作系统、数据库软件、以及提供部署功能的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 服务器网关接口。
二:WSGI简介
PythonWeb服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是一个协议,是 Python应用程序或框架 与 Web容器 之间的一种接口规范。
只要双方都按照这个规范,分别去实现自己需要做的事,那么二者就可以顺利地进行通信。
WSGI
协议主要包括server
和application
两部分。
三:WSGI server接口
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接口
WSGI application接口
接收由server
转发过来的request
,处理请求,并将处理结果返回给server
。
接口的实现方式:
- 应用程序必须是一个可调用的对象
可调用的对象有三种:- 一个函数
- 一个类,必须实现__call__()方法
- 一个类的实例
-
这个对象接收两个参数
从源码中,我们可以看到,这两个参数是environ, start_response. 以可调用对象为一个类为例:class application: def __call__(self, environ, start_response): pass
-
可调用对象需要返回一个可迭代的值。以可调用对象为一个类为例:
class application: def __call__(self, environ, start_response): return [xxx]
五:Middleware 中间件
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
框架,可以根据项目实际情况搭配使用。
七:扩展:uwsgi
uwsgi:与WSGI
一样是一种通信协议,是
uWSGI
服务器的独占协议,用于定义传输信息的类型(
type of information
),每一个
uwsgi packet
前
4byte
为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是
fcgi
协议的10倍快。
八:扩展:uWSGI
uWSGI
旨在为部署分布式集群的网络应用开发一套完整的解决方案。主要面向web
及其标准服务。由于其可扩展性,能够被无限制的扩展用来支持更多平台和语言。uWSGI
是一个web
服务器,实现了WSGI
协议,uwsgi
协议,http
协议等。uWSGI
的主要特点是:
- 超快的性能
- 低内存占用
- 多
app
管理 - 详尽的日志功能(可以用来分析
app
的性能和瓶颈) - 高度可定制(内存大小限制,服务一定次数后重启等)
uWSGI
服务器自己实现了基于uwsgi
协议的server
部分,我们只需要在uwsgi
的配置文件中指定application
的地址,uWSGI
就能直接和应用框架中的WSGI application
通信。