前言(一般这里说下写文章的原因):
首先作为一个QA,写过大大下下的web项目有十几个了,但是遗憾的是一直没有一个项目的使用压力能达到项目瓶颈(阿里云2核4G的ECS),其实我只是用django+uwsgi+nginx这套东西,当然有一些自以为是的调优,但是压力确实全都没上去,自己压测感觉也不是真实数据,当然压力大了uwsgi会突突突报错,但是最近还是在思考python的高并发解决方案,说句糟心的话,万一有一个项目到了呢,不至于措手不及
。
首先我不质疑django+uwsgi+nginx这套架构,说实话开发项目速度贼快,小打小闹的压力也还可以,但是总是要追求下更好。以下只是小编自己的调研和YY,欢迎大牛指正。
首先说一下linux解决高并发的机制就是著名的IO多路复用了,三种机制epoll\poll\select,想详细了解的同学可以谷歌查下啦,这里只是简单粗略的说说自己的理解,这三个东西。
我们都知道,当一个请求到达服务器,也就是进行soket通信时,是通过套接字接受一个连接并开启一个线程进行通信,但是这个时候我们并不知道客户端的信息有没有发完,肯定有发一大坨过来的数据,要接收好久,那得了,我们咋知道客户端发送完了呢,这就有两种方法了。
1、死磕,就在这等着你,发完了我在走。
2、你发吧,我一会来问问,要是没发问,我就一会在来问问。
很显然第二种方法好太多,不占用时间,如果高并发有多个连接,可以在一定时间轮询,看有没有数据读写,这样就可以并发处理了,这个其实就是poll和select的解决方案,当然详细的比我说的复杂的多的多。虽然看起来问题解决了,但是随着连接的越来越多,轮询查看的时间就越来越久,而且很多soket连接是不活跃的,这浪费了大量的时间。因为这个时间大牛们对poll进行了升级,此时epoll出来了,他可以只轮询活跃的soket连接,这就节省了大量的时间。
那知道epoll这东西好,就去研究研究epoll吧。
其实epoll很简单,提供了四个核心api
1、epoll_create
用来创建epoll描述符的,就是创建用。
2、epoll_ctl:
操作epoll的方法封装在这个里面,包括EPOLL_CTL_ADD(新增一个epoll)\EPOLL_CTL_DEL(删除一个epoll)\EPOLL_CTL_MOD(改变epoll的监听方式)
改变监听方式又有7种,这里就不一个一个说了,重要的有三个:EPOLLIN,可读,缓冲器满\EPOLLOUT(可写,缓冲区空)\EPOLLERR(发送错误)
3、epoll_wait
让epoll开始工作,其中timeout参数;大于0-监听(阻塞)时间、等于0-立即返回、等于-1一直监听
4、close
关闭epoll
好了为啥和大家说上面这一堆,其实是想说,用epoll,是linunx下最快高并发解决方案,那目标就是linux下的py使用epoll的web框架了。
然后找到了tornado--开始潜心调研。
写过tornado的小伙都知道启动tornado服务最后的启动语句是
tornado.ioloop.IOLoop.current().start()
重点 就在tornado.ioloop这个文件里面,这个里面机智的封装了epoll里面上面说的四个api,良心啊。
既然了解了tornado,说一说高并发怎么搞吧。
nginx做反向代理,启动多个分发模块,分发给多个启动的tornado进程,比如nginx启动在80端口,根据模块分给8001、8002、8003等等,启动多个tornado服务。因为python毕竟有GIL这东西,一个进程永远不能多线程,特别是连接数据库,感觉这里会有瓶颈,所以用nginx做反向代理,tornado起多进程。
当然用惯了django的我不会落下这东西的,把django的orm,中间节等特性和tornado结合,在tornado中可以使用dj的特性,同时支持tornado中的异步回调。
最后说的python,肯定是pypy啦。
所以最后准备 用nginx+tornado+django+pypy,数据库mysql,包管理机conda.
补一句,如果上面的方案不行,后面会使用lua(openrestry)--我负责项目使用的,或者使用go(未开始调研)。
折腾完继续更新文章~
转载务必标明出处!!