前言(一般這里說下寫文章的原因):
首先作為一個QA傀蓉,寫過大大下下的web項目有十幾個了,但是遺憾的是一直沒有一個項目的使用壓力能達到項目瓶頸(阿里云2核4G的ECS)职抡,其實我只是用django+uwsgi+nginx這套東西葬燎,當然有一些自以為是的調(diào)優(yōu),但是壓力確實全都沒上去缚甩,自己壓測感覺也不是真實數(shù)據(jù)谱净,當然壓力大了uwsgi會突突突報錯,但是最近還是在思考python的高并發(fā)解決方案擅威,說句糟心的話壕探,萬一有一個項目到了呢,不至于措手不及
郊丛。
首先我不質(zhì)疑django+uwsgi+nginx這套架構李请,說實話開發(fā)項目速度賊快,小打小鬧的壓力也還可以厉熟,但是總是要追求下更好导盅。以下只是小編自己的調(diào)研和YY,歡迎大牛指正揍瑟。
首先說一下linux解決高并發(fā)的機制就是著名的IO多路復用了,三種機制epoll\poll\select白翻,想詳細了解的同學可以谷歌查下啦,這里只是簡單粗略的說說自己的理解绢片,這三個東西滤馍。
我們都知道,當一個請求到達服務器底循,也就是進行soket通信時巢株,是通過套接字接受一個連接并開啟一個線程進行通信,但是這個時候我們并不知道客戶端的信息有沒有發(fā)完此叠,肯定有發(fā)一大坨過來的數(shù)據(jù)纯续,要接收好久,那得了灭袁,我們咋知道客戶端發(fā)送完了呢猬错,這就有兩種方法了。
1茸歧、死磕倦炒,就在這等著你,發(fā)完了我在走软瞎。
2逢唤、你發(fā)吧拉讯,我一會來問問,要是沒發(fā)問鳖藕,我就一會在來問問魔慷。
很顯然第二種方法好太多,不占用時間著恩,如果高并發(fā)有多個連接院尔,可以在一定時間輪詢,看有沒有數(shù)據(jù)讀寫喉誊,這樣就可以并發(fā)處理了邀摆,這個其實就是poll和select的解決方案,當然詳細的比我說的復雜的多的多伍茄。雖然看起來問題解決了栋盹,但是隨著連接的越來越多,輪詢查看的時間就越來越久敷矫,而且很多soket連接是不活躍的例获,這浪費了大量的時間。因為這個時間大牛們對poll進行了升級沪饺,此時epoll出來了躏敢,他可以只輪詢活躍的soket連接闷愤,這就節(jié)省了大量的時間整葡。
那知道epoll這東西好,就去研究研究epoll吧讥脐。
其實epoll很簡單遭居,提供了四個核心api
1、epoll_create
用來創(chuàng)建epoll描述符的旬渠,就是創(chuàng)建用俱萍。
2、epoll_ctl:
操作epoll的方法封裝在這個里面告丢,包括EPOLL_CTL_ADD(新增一個epoll)\EPOLL_CTL_DEL(刪除一個epoll)\EPOLL_CTL_MOD(改變epoll的監(jiān)聽方式)
改變監(jiān)聽方式又有7種枪蘑,這里就不一個一個說了,重要的有三個:EPOLLIN岖免,可讀岳颇,緩沖器滿\EPOLLOUT(可寫,緩沖區(qū)空)\EPOLLERR(發(fā)送錯誤)
3颅湘、epoll_wait
讓epoll開始工作话侧,其中timeout參數(shù);大于0-監(jiān)聽(阻塞)時間、等于0-立即返回闯参、等于-1一直監(jiān)聽
4瞻鹏、close
關閉epoll
好了為啥和大家說上面這一堆悲立,其實是想說,用epoll新博,是linunx下最快高并發(fā)解決方案薪夕,那目標就是linux下的py使用epoll的web框架了。
然后找到了tornado--開始潛心調(diào)研赫悄。
寫過tornado的小伙都知道啟動tornado服務最后的啟動語句是
tornado.ioloop.IOLoop.current().start()
重點 就在tornado.ioloop這個文件里面寥殖,這個里面機智的封裝了epoll里面上面說的四個api,良心啊涩蜘。
既然了解了tornado嚼贡,說一說高并發(fā)怎么搞吧。
nginx做反向代理同诫,啟動多個分發(fā)模塊粤策,分發(fā)給多個啟動的tornado進程,比如nginx啟動在80端口误窖,根據(jù)模塊分給8001叮盘、8002、8003等等霹俺,啟動多個tornado服務柔吼。因為python畢竟有GIL這東西,一個進程永遠不能多線程丙唧,特別是連接數(shù)據(jù)庫愈魏,感覺這里會有瓶頸,所以用nginx做反向代理想际,tornado起多進程培漏。
當然用慣了django的我不會落下這東西的,把django的orm胡本,中間節(jié)等特性和tornado結(jié)合牌柄,在tornado中可以使用dj的特性,同時支持tornado中的異步回調(diào)侧甫。
最后說的python珊佣,肯定是pypy啦。
所以最后準備 用nginx+tornado+django+pypy,數(shù)據(jù)庫mysql披粟,包管理機conda.
補一句咒锻,如果上面的方案不行,后面會使用lua(openrestry)--我負責項目使用的,或者使用go(未開始調(diào)研)僻爽。
折騰完繼續(xù)更新文章~
轉(zhuǎn)載務必標明出處3娴铩!