django 的并发能力真的是令人担忧,django本身框架下只有一个线程在处理请求,任何一个请求阻塞,就会影响另一个情感求的响应,尤其是涉及到IO操作时,基于框架下开发的视图的响应并没有对应的开启多线程,再者Python的多线程对于多核CPU有效利用率非常低,参照
这里就使用 nginx + uwsgi 提供高并发
nginx 的并发能力超高,单台并发能力过万(这个也不是绝对),在纯静态的 web 服务中更是突出其优越的地方,由于其底层使用 epoll 异步IO模型进行处理,使其深受欢迎
做过运维的应该都知道,php 需要使用 nginx + fastcgi 提供高并发,java 需要使用 nginx + tomcat 提供 web 服务
原因很简单,因为自增主键的存在写库存在抢锁, 可以利用全局id生成器提前生成id直接写入数据库
如果数据只是存在mysql中做备份,建议使用异步的方式写入库,先把数据写到缓存下发给用户,之后在利用后台异步任务一点点的写入,例如聊天系统可以这样干
可以试试tornado, 如果tornado依然无法满足,可以尝试使用golango,毕竟golang是以高并发著称, 而且是编译语言,而且基于它的web框架也很容易上手,性能很可观,例如Iris
======================================
django
毫无疑问,用原生django的server做处理的表现是最烂的,在10000次请求的情况下brokenpipe的几率极高,只有1400次请求被处理,成功率只有14%,我也懒得继续测下去了。
django + nginx
这次搭上了nginx做反向代理,也使的脆弱的django服务器的情况有所缓解,但成功率仍然不高(10000次请求中有3684个请求被处理)。
uwsgi + nginx
uwsgi是性能极高的一个由C编写的服务器,它使用uwsgi协议,这次让它配合nginx处理django的request,参数为4进程+2线程,性能立即直线上升,处理请求的成功率也基本在90%左右,不过我在测试时遇到了一个坑,就是uwsgi在处理请求的时候发送了队列溢出的问题,因为当前测试设置的并发数为每秒1000次并发,而uwsgi的处理队列容量默认为100,导致处理请求的时间加长,而这个问题则可以通过修改somaxcon的大小解决,总的来说,使用uwsgi+nginx是一个理想的选择。
gunicorn + nginx
gunicorn跟uwsgi类似,也是一个高性能的http服务器,它由ruby的unicorn项目移植,是由python编写的,它的配置简单,而且可以灵活地搭配其他网络库,部署十分方便,在测试数据中可以看到,用这种配置运行django能在短时间内就能处理大量的并发请求,成功率在90%左右。
gunicorn + nginx + gevent
前面说的几种环境,看似不错,但我们需要追求完美!由于gunicorn是同步(sync)单线程模型的,有的时候它不免会发生一些阻塞问题,这时候我们为gunicorn加上-k gevent参数来用gevent做处理接口,这就比较靠谱地处理了阻塞问题,从数据中可以看到,gunicorn + nginx + gevent的模式不仅拥有100%的处理成功率,而且时间也在很短之内完成,是5组测试数据当中的性能最好的。
=======================================
其实 WSGI 是分成 server 和 framework (即 application) 两部分 (当然还有 middleware)。
严格说 WSGI 只是一个协议, 规范 server 和 framework 之间连接的接口。
WSGI server 把服务器功能以 WSGI 接口暴露出来。比如 mod_wsgi 是一种 server, 把 apache 的功能以 WSGI 接口的形式提供出来。
uWSGI 的主要特点如下:
=========================================
https://segmentfault.com/q/1010000002548045
学习tornado时,发现tornado的异步请求使用tornado.gen或者callback实现。
做实验两个请求,一个sleep上5秒,一个立即返回。先请求sleep,再请求立即返回的。 发现django并没有做什么处理。同样可以在第一个请求sleep时,不影响第二个立即返回的请求。请问下django是怎么处理的。
你应该是使用了Django自己的开发服务器跑的例子,在Django关于manage.py的文档中写道:
--nothreading
The development server is multithreaded by default. Use the --nothreading option to disable the use of threading in the development server.
也就是说,默认情况下你使用./manage.py runserver
会开启多个线程对HTTP请求进行伺服,所以第二个请求进来时虽然第一个请求仍在sleep,但已经新开了一个线程进行响应处理,看起来像是“非阻塞”的工作模式,其实质是多线程而非单线程,想禁用这一行为也已经给出了答案,加上--nothreading
参数:./manage.py runserver --nothreading
即可。
Django就没有用异步,通过线程来实现并发,这也是WSGI普遍的做法,跟tornado不是一个概念