uWSGI 是一个快速的、纯C语言开发的、自维护的、对开发者友好的 WSGI 服务器,旨在提供专业的 Python web应用发布和开发。可使用 C/C++/Objective-C 来为 uWSGI 编写插件。在这里要区分三个概念:
- WSGI:全称是Web Server Gateway Interface,WSGI不是服务器、python模块、框架、API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle,Flask,Django。
- uwsgi:与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。
- uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。
1. WSGI协议
WSGI协议主要包括server和application两部分:
- WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;
- WSGI application接收由server转发的request,处理请求,并将处理结果返回给server。application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application,因此可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。
WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,那么就可以选择任意的server和application组合实现自己的web应用。例如uWSGI和Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。
图1 wsgi协议
WSGI 规定每个 python 程序(Application)必须是一个可调用的对象(函数或者是实现了__call__
方法的类),接受两个参数 environ
(WSGI 的环境信息) 和 start_response
(开始响应请求的函数),并且返回 iterable。几点说明:
environ
和start_response
由 http server 提供并实现environ
变量是包含了环境信息的字典Application
内部在返回前调用start_response
start_response
也是一个 callable,接受两个必须的参数,status
(HTTP状态)和response_headers
(响应消息的头)- 可调用对象要返回一个值,这个值是可迭代的。
下面是wsgi一个具体实现
- 应用程序
#!/usr/bin/env python
# coding:utf-8
def application(environ,start_response):start_response("200 ok",[('ContentType','text/html')])return [b"<h1>hello world</h1>"]
- 服务器
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()
可以看出application的流程包括:
- 接收http服务器发送过来的用户请求信息(environ);
- 处理请求,调用get_response()方法处理当前请求。
- 调用由server传入的start_response()方法将响应header与status返回给server。
- 返回响应正文
2.uWSGI
uWSGI旨在为部署分布式集群的网络应用开发一套完整的解决方案。主要面向web及其标准服务。由于其可扩展性,能够被无限制的扩展用来支持更多平台和语言。uWSGI是一个web应用服务器,实现了WSGI协议,uwsgi协议,http协议等。 uWSGI的主要特点是:
- 超快的性能
- 低内存占用
- 多app管理
- 详尽的日志功能(可以用来分析app的性能和瓶颈)
- 高度可定制(内存大小限制,服务一定次数后重启等)
uWSGI服务器自己实现了基于uwsgi协议的server部分,我们只需要在uwsgi的配置文件中指定application的地址,uWSGI就能直接和应用框架中的WSGI application通信。
3 nginx+uWsgi实现站点的部署
uWSGI做为一款优秀的python应用服务器,更擅长处理动态请求,实际开发中一般用nginx处理静态请求,动态请求转发给uWsgi服务器处理。其架构如图1所示。
nginx作为web服务器有以下特点:
- 它处理静态文件和索引文件效果非常高,配合uWSGI服务器会更加安全;
- 它的设计非常注重效率,最大支持 5 万个并发连接,但只占用很少的内存空间;
- 稳定性高,配置简洁
- 强大的反向代理和负载均衡功能,平衡集群中各个服务器的负载压力应用
而uWsgi服务器虽然也能够处理静态请求,但效率远不如nginx,并且从安全性和可扩展性方面来讲,使用nginx+uWsgi是最佳方式。所以,一般python后端开发一般采取nginx+uWsgi+Django/Flask应用的方式部署。
一般首先是浏览器发起 http 请求到 nginx 服务器,Nginx 根据接收到请求包,进行 url 分析,判断访问的资源类型:如果是静态资源,直接读取静态资源返回给浏览器。如果请求的是动态资源就转交给 uwsgi服务器,uwsgi 服务器根据自身的 uwsgi 和 WSGI 协议,找到对应的 Django 框架/Flask框架,Django 框架/Flask框架下的应用进行逻辑处理后,将返回值发送到 uwsgi 服务器,然后 uwsgi 服务器再返回给 nginx,最后 nginx将返回值返回给浏览器进行渲染显示给用户。