前因

       关于WSGI、uWSGI、uwsgi、Nginx这些名词及与Django 项目的关系,之前有个善(漂)良(亮)的小姐姐问过我,当时我也不是很明白,没有给她解释的很清楚,很是后悔,现在结合网上的一些资料进行一下汇总,且加入了一些我自己的看法,有不足之处还望路过的大佬给予批评指正,拜谢!

名词介绍

WSGI (通信协议)

全称Web Server Gateway Interface(Web服务器网关接口),它不是服务器、Python模块、框架、API或者任何软件,只是一种描述Web 服务器(如nginx,uWSGI 等服务器)如何与Web 应用程序(如用Django、Flask框架写的程序)通信的规范,是一种实现了比如Python 解析的通用接口标准/标准,实现了Python Web 程序与服务器交互的通用性,利用这个协议,Web 项目就可以轻松部署在不同的Web Server 上了。

 

uWSGI(服务器)

uWSGI 是一个全功能的HTTP 服务器,实现了WSGI 协议、uwsgi协议、http协议等,它要做的就是把HTTP协议转化成语言支持的网络协议,比如把HTTP协议转换成WSGI 协议,让Python 可以直接使用。

 

uwsgi(线路协议)

与WSGI 一样,是uWSGI服务器的独占通信协议,用于定义传输信息的类型(type of information)。每一个uwsgi packet 前4 byte 为传输信息类型的描述,与WSGI 协议是两种东西,据说该协议是fcgi协议的10倍快。

 

Nginx

Nginx 是一个开源的高性能的HTTP 服务器和反向代理,具体作用:
1.可以作为web 服务器,处理静态文件和索引文件效率非常高;
2.它的设计非常注重效率,最大支持5万个并发连接,但是只占用很少的内存空间;
3.稳定性高,配置简洁;
4.还可以用于强大的反向代理和负载均衡功能,平衡集群中各个服务器的负载压力应用。

很多资料上都有的一句话,交代了这几个名词的关系:uWSGI 服务器实现了WSGI协议,uwsgi协议,http协议等等,Nginx 中的HttpUwsgiModule 的作用是与uWSGI 服务器进行交换。

 

以Django 框架开发为例

Django

Django 是一个Web框架,框架的作用在于处理request 和response,其他的不是框架所关心的内容,所以如何部署Django 也不是Django 所需要关心的。
Django 所提供的是一个开发服务器,这个开发服务器,没有经过安全测试,而且使用的是Python 自带的simple HTTPServer 创建的,如果你看了Django 源码就知道,runserver 起来的HTTPServer 就是Python 自带的simple HTTPServer,所以在安全性和效率上都是不行的。

在Django 开发的Web 应用程序中,nginx和uWSGI 服务器之间是如何配合工作的?

Nginx,uWSGI与Django 应用的关系

 

1.首先客户端发送http 请求,来获取服务器资源;
2.Nginx 作为直接对外的服务器接口,接收到客户端发过来的http请求,然后进行解包、分析;
3.如果是静态资源的请求,会根据nginx 配置的静态文件目录,返回请求的资源;
4.如果是动态资源的请求,nginx 就会通过配置,将请求传递给uWSGI 服务器;
5.uWSGI 将接收到的数据包进行处理,并转发给WSGI(HTTP 协议转成WSGI 协议);
6.WSGI 根据请求调用Django 项目中的某个文件或函数,进行逻辑处理,完成后Django 将返回值交给WSGI;
7.WSGI 将返回值打包,转发给uWSGI 服务器(WSGI 协议转换成HTTP 协议);
8.uWSGI 服务器接收后转发给Nginx 服务器,最终Nginx 服务器将返回值返回给客户端(如浏览器)
注意:不同的组件之间传递信息涉及到数据格式和协议的转换

 

关于Nginx

1.第一级的Nginx 并不是必须的,uwsgi 完全可以完成整个和浏览器交互的流程;
2.在Nginx 上加上安全性或其他得限制,可以达到保护程序的作用;
3.uWSGI 本身是内网接口,开启多个work 和processes 可能也不够用,而Nginx 可以代理多台uWSGI 完成uWSGI 负载均衡;
4.Django 在Debug=Flase 下对静态文件的处理能力不是很好,而用Nginx 来处理会更加高效

 

       一个成熟的站点提供服务,需要Web 服务器(静态数据)和APP 服务器(动态数据)。Web 服务器目前属Nginx 最强大,用户请求代理过来后,把静态数据返回给客户端。但是目前的互联网发展时代,都是包含动态数据处理的,Nginx 不处理业务逻辑,都外包给后端的APP 服务器,比如Django 框架开发的服务器。

       再需要性能优化的场景,单单通过Nginx 和uWSGI 也是不够的,Nginx 主要的优化是连接数和处理静态资源的请求,uWSGI 主要优化的是WSGI 服务,这些都只是手段,其他手段包括:优化数据库、增加缓存、加入负载均衡、引入异步IO 框架(如gunicorn 服务器的gevent 框架)、计算密集型模块用C 重写等。安全性方面,也有很多考虑,原作者没有展开介绍:)

 

扩展

下面是我之前截图的一个大佬自己测试的各种配置的性能对比,原帖暂时找不到,如果大佬看见了,请在下面留言,我会根据您的要求,添加或删除这部分资料,谢谢

1.Django

毫无疑问,用原生Django 的Server 做处理的表现是最烂的(上面介绍了,Django 原生的Server 就是Python 自带的simple HTTPServer 创建的),在10000 次请求的情况下,broken pipe (就是请求失败吧)的几率极高,只有1400次请求被处理,成功了只有14%,原作者懒得继续测下去了(以后有机会我也测试测试)。

2.Django + Nginx

这次搭上了Nginx 做反向代理,也使得脆弱的Django 服务器的情况有所缓解,但成功率仍然不高(10000 次请求中有3684 个请求被处理)。

3.uWSGI + Nginx

uWSGI 是性能极高的一个由C 编写的服务器,使用了自身独占的uwsgi 协议,这次让它配合Nginx 处理Django 的request,参数为4 进程 + 2 线程,性能立即直线商城,处理请求的成功率也基本在90% 左右,原作者在测试的时候遇到了一个坑,就是uWSGI 在处理请求的时候发送了队列溢出的问题,因为当前测试设置的并发数为每秒1000 次并发,而uWSGI 的处理队列的容量默认是100*(启动的uWSGI 的进程数),导致处理请求的时间加长,而这个问题则可以通过修改somaxcon 的大小解决(具体做法在5 个配置下面 ),总的来说,使用uWSGI + Nginx 是一个理想的选择。

4.Gunicorn + Nginx

gunicorn 跟 uWSGI 类似,也是一个高性能的http 服务器,它由ruby 的unicorn 项目移植,是由Python 编写的,它的配置简单,而且可以灵活的搭配其他网络库,部署十分方便,在测试数据中可以看到,用这种配置运行Django 能在短时间内就能处理大量的并发请求,成功率在90% 左右。
(我们之前这种配置都是配置Flask 框架开发的Web 服务器)

5.Gunicorn + Nginx +Gevent

前面说的几种环境,看似不错,但是作者说了,我们需要追求完美!由于gunicorn 是同步(sync)单线程模型的,有时候不免会发生一些阻塞问题,这时候我们为gunicorn 加上 -k gevent 参数来用gevent 做处理接口,这就比较靠谱的处理了阻塞问题,从作者的测试结果可以得到,这种模式下不仅拥有100% 的处理成功率,而且时间也在很短之内完成,是5组测试数据当中性能最好的!
补充一句:原作者好棒!

 

uWSGI listen queue 队列溢出的修补措施:

1.修改系统参数
vim /etc/sysctl.conf
在文件最后添加一行记录net.core.somaxcon = 1024
执行sysctl -p重新load参数设置,这样会立即生效,并且以后重新启动机器也会生效。

2.设置uwsgi启动的--listen 1024.
这样 你的机器并发数就可以得到一个很大的提升。

 

参考:

1.百度百科

2.uWSGI + django + nginx 的工作原理流程与部署历程:https://blog.csdn.net/c465869935/article/details/53242126

3.uWSGI listen queue 队列溢出的问题:http://www.cnblogs.com/zhujie/archive/2012/04/27/2474051.html