利用gevent來配置uwsgi提高django項目並發量


add by zhj:

Benchmark of Python WSGI Servers一文中,作者進行詳細分析,得出的結論是gevent在所有WSGI Server(包括Tornado、Uwsgi等)中性能最好。

另外,我想說gevent適合socket IO,其它類型的IO,如磁盤IO是否適合就不清楚了。

 

原文:https://co-ding.com/?p=356#comment-6036

我的一個線上web服務在生產中遇到一個性能問題:當初為了方便選擇了wsgi(眾所周知wsgi協議,不像tornado之類的的框架可以使用異步IO),

而服務本身有大量IO(倒並不是帶寬很大,只是會經常阻塞),因此一個業務完成可能需要很長時間幾秒甚至十幾秒。

我使用uwsgi這樣啟動:

uwsgi --harakiri 25 --harakiri-verbose --http :9090 -M  --processes 12 --threads 2 --wsgi-file wsgi.py

也就是說同時並發量為 12*2=24,這是在以后服務量增長之后是完全不能接受的。

因此,我開始考慮增加線程數,使用siege測試發現線程數過多的時候,由於線程上下文切換導致效率很低,本來5秒鍾的業務,最后平均7s才能完成,

這其中有2秒鍾用在了線程切換上面

siege -r 2 -c 50  "http://127.0.0.1:9090/api POST <./test.post"

於是考慮使用異步框架,tornado,gevent之類的。

我首先看了下tornado,tornado是一個web框架,它同時也提供了很多異步的庫,包括httpclient(Asynchronous HTTP client)。因此我的程序要想在tornado上面跑並

發揮異步的作用,必須修改大量代碼,將所有的IO操作更換成tornado提供的異步函數。這本身是不可接受的,不如直接增加進程/線程來的方便。

接下來我看了下gevent,gevent是使用greenlet協程Coroutine來實現異步網絡框架,而且它提供了一個異常方便了monkey模塊,可以在不修改原來

的使用python標准庫函數的程序的情況下,將程序轉換成可以使用gevent框架的異步程序。

即:

from gevent import monkey
# patches stdlib (including socket and ssl modules) to cooperate with other greenlets
monkey.patch_all()

gevent雖然也自帶一個wsgi server,但是畢竟不是專業的web服務器,我們還是要使用uwsgi的。然后我發現uwsgi對gevent的支持還是很好的,

直接使用下面的命令啟動,甚至不需要改動一行代碼。(add by zhj: 在uwsgi中如果使用了gevent參數,就不能用thread參數了,不過,貌似仍可以在進程中創建線程)

uwsgi --gevent 100 --gevent-monkey-patch --http :9090 -M  --processes 4 --wsgi-file wsgi.py

--gevent參數后面的100, 制定了最大spawn 100個協程,這樣我們的理論並發數可以達到 100*4。

使用了參數 --gevent-monkey-patch 讓我們連最后需要修改代碼的地方都沒有了:它將自動調用monkey.patch_all()打補丁。

這樣,我們就一句代碼都沒有修改,就使程序轉換為異步的程序,大大提高並發數。與提高線程數相比,大大減少了線程切換的開銷(協程之間切換的代價很低)。

 

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM