Python的Web开发中,如果使用Django框架,那么较为成熟稳定的服务器架构一般是Nginx+uWSGI+Django。而为什么一定要三个结合在一起呢?直接使用Django的runserver来启动服务器进程,或者uWSGI+Django可不可以呢?为什么?
概念说明:
APP(应用程序),就是开发者写的应用程序,例如django,bottle这些。记录怎么处理客户端发来的请求的逻辑部分。
WSGI,是一个协议,Python用于Web开发的协议
uWSGI,是一个程序,充当Web服务器或中间件。
如果架构是Nginx+uWSGI+APP,uWSGI是一个中间件
如果架构是uWSGI+APP,uWSGI是一个服务器
uwsgi,是uWSGI程序实现的一个自有的协议。
Web协议出现顺序:
CGI -> FCGI -> WSGI -> uwsgi
CGI,最早的协议
FCGI,比CGI快
WSGI,Python专用的协议
uwsgi,比FCGI和WSGI都快,是uWSGI项目自有的协议,主要特征是采用二进制来存储数据,之前的协议都是使用字符串,所以在存储空间和解析速度上,都优于字符串型协议.
一、WSGI协议浏览器请求一个页面的流程:
浏览器发送请求给服务器,包含请求头和请求体
服务器解析请求头和请求体
服务器根据请求信息来处理请求,生成返回内容
服务器生成响应头和响应体
服务器返回响应给浏览器,浏览器显示给用户
一个网站,一般有很多个不同的请求,在这些请求中,基本1,2,4,5部都是固定的,变的只有第三步,所以把这四步抽象出来,让开发者只关注第三步,这样就可以极大提升开发效率。所以WSGI协议诞生了。
WSGI,全称 Web Server Gateway Interface。是Python专用的协议,其他语言没有。用于处理Web服务器和应用程序(APP)的交互信息。很多Web框架(如:django)都会自带WSGI服务器,但是性能不好,只作测试用途。
实现一个最简单的服务器
app.py
import pprint
def application(environ, start_response):
pprint.pprint(environ)
start_response('200 OK',[('Content-Type','text/html')])
return'<h1>Hello, web!</h1>'
environ参数是一个字典对象,保存HTTP请求的信息。例如URL路径,域名,请求头,请求参数等
start_response参数是一个函数,用于向wsgiref提供响应头的设置,只能调用一次。
server.py
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from app import application
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('',8000, application)
print"Serving HTTP on port 8000..."
# 开始监听HTTP请求:
httpd.serve_forever()
启动python server.py,就可以通过localhost:8000访问了
wsgiref模块是python提供的,用于测试和学习的简单的WSGI服务器模块。
这个模块监听8000端口,把Http请求,根据WSGI协议,转换application函数中的environ参数,然后调用application函数。
wsgiref会把application函数提供的响应头设置转换为HTTP协议的响应头,把application的返回(return)作为响应体,根据HTTP协议,生成响应,返回给浏览器。
这样,应用程序就不需要关注底层的HTTP协议细则了
二、CGI和FastCGICGI是Common Gateway Interface,即通用网关接口,是一个协议,是外部应用程序(CGI程序)与Web服务器之间的接口标准。该协议定义了Web服务器在调用应用程序时需要传输的参数和应用程序怎么返回结果给Web服务器,其实跟WSGI类似。
CGI的一个特点是,对于每一个HTTP请求,Web服务器都会新建一个进程(fork),等应用程序返回结果后,这个进程就会结束。这样的后果是,一旦HTTP请求多的时候,Web服务器会频繁创建进程,大家都知道,创建进程的开销是非常大的,所以这种做法会影响服务器的性能,所以就有了FastCGI。
FCGI的做法是在Web服务器启动的时候,就创建多个应用程序进程,当Web服务器接收到HTTP请求时,就把请求分发给其中一个空闲的进程。相当于MYSQL连接池的原理。这样就可以避免频繁地fork进程。FCGI另一个特点是支持分布式,也就是Web服务器和应用程序可以在不同的机器。
CGI和WSGI的区别是:
Ningx是一个反向代理服务器
什么是反向代理?
正向代理,例如FQ用的代理服务器就是正向代理,浏览器主动请求代理服务器,代理服务器转发请求到对应的目标服务器