首先理解下面三个概念:html
WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通讯的规范。python
uwsgi:与WSGI同样是一种协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,听说该协议是fcgi协议的10倍快。web
uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。后端
WSGI协议主要包括server和application两部分:浏览器
其中application部分:服务器
示例代码:app
def application(environ, start_response): status = '200 OK' response_headers = [('Content-Type', 'text/html')] # application内部调用start_response start_response(status, response_headers) # 解析environ信息,业务逻辑处理后,返回对应的响应信息(下面代码只是模拟业务处理) file_name = environ['PATH_INFO'] if file_name == "/index.py": return index(file_name) elif file_name == "/center.py": return center(file_name) else: return 'Hello world a simple WSGI application!'
有了WSGI,咱们在框架中只关心如何从environ这个dict(wgsi规定传过来一个字典)对象拿到HTTP请求信息,而后构造HTML,经过start_response()发送Header,最后返回Body。框架
整个application()函数自己没有涉及到任何解析HTTP的部分。 也就是说,底层代码不须要咱们本身编写,咱们只负责业务逻辑部分便可。socket
可是咱们想一下,这个application()函数怎么调用?若是咱们本身调用,两个参数environ和start_response咱们无法提供,返回的str也无法发给浏览器。函数
截取server端部分代码实例以下:
# 重点关注逻辑 # 准备一个字典,里面存放须要传递给web框架的数据 env = dict() # ----------更新--------- env['PATH_INFO'] = file_name # 例如 index.py(模拟请求信息) # 重点关注逻辑 # 服务器调用框架中实现的application函数,并将包含请求信息的字典和获取响应头的函数传入 response_body = self.application(env, self.start_response) # 合并header和body(响应客户端的请求,这个逻辑不用关注) response_header = "HTTP/1.1 {status}\r\n".format(status=self.headers[0]) response_header += "Content-Type: text/html; charset=utf-8\r\n" response_header += "Content-Length: %d\r\n" % len(response_body.encode("utf-8")) for temp_head in self.headers[1]: response_header += "{0}:{1}\r\n".format(*temp_head) response = response_header + "\r\n" response += response_body client_socket.send(response.encode('utf-8')) # 重点关注逻辑 # server端实现了start_response函数的定义 def start_response(self, status, headers): """这个方法,会在 web框架中被默认调用""" response_header_default = [ ("Data", time.time()), ("Server", "ItCast-python mini web server") ] # 将状态码/相应头信息存储起来 # [字符串, [xxxxx, xxx2]] self.headers = [status, response_header_default + headers]
这段代码,是在客户端请求动态资源时启动,即服务器须要向后端框架请求资源。代码解析已在代码中注释。
因此咱们基本能够得到以下结论:
要实现WSGI协议,必须同时实现web server端和web application端
当前运行在WSGI协议之上的web框架有Torando,Flask,Django等
比较经常使用的WSGI协议服务器有:uWSGI,gunicorn等
一、框架须要实现WSGI协议,例如:Flask,Django等
二、environ 和 start_response 由 http server 提供并实现
三、environ 变量是包含了请求信息的字典
四、Application 内部在返回前调用 start_response
五、application()函数必须由WSGI服务器来调用
server要履行的任务:
一、接收HTTP请求
二、解析HTTP请求
三、准备 environ请求参数
四、定义 start_response 函数
五、组装响应头和相应体返回给客户端
application要履行的责任:
一、解析服务器发来的请求信息
二、根据请求信息,进行业务处理
三、返回所须要的数据
至此,您应该对WSGI有了必定的了解吧。
扩展阅读:
目前一些主要的实现了WSGI协议的服务器:
gunicorn
Gunicorn(从Ruby下面的Unicorn发展而来):依赖Nginx的代理行为,同Nginx进行功能上的分离。因为不须要直接处理用户来的请求(都被Nginx先处理),Gunicorn不须要完成相关的功能,其内部逻辑很是简单:接受从Nginx来的动态请求,处理完以后返回给Nginx,由后者返回给用户。
因为功能定位很明确,Gunicorn得以用纯Python开发:大大缩短了开发时间的同时,性能上也不会很掉链子。同时,它也能够配合Nginx的代理以外的别的Proxy模块工做,其配置也相应比较简单。
配置上的简单,大概是它流行的最大的缘由。
uWSGI
由于使用C语言开发,会和底层接触的更好,配置也是比较方便,目前和gunicorn两个算是部署时的惟二之选。
如下是一般的配置文件
fcgi
很少说,用的少。
bjoern