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应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。

nginx+uWsgi应用部署方式_flask

 

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。几点说明:

  1. environ 和 start_response 由 http server 提供并实现
  2. environ 变量是包含了环境信息的字典
  3. Application 内部在返回前调用 start_response
  4. start_response也是一个 callable,接受两个必须的参数,status(HTTP状态)和 response_headers(响应消息的头)
  5. 可调用对象要返回一个值,这个值是可迭代的。

下面是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+uWsgi应用部署方式_python_02

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将返回值返回给浏览器进行渲染显示给用户。