高效能架構gevent和gunicorn在web上的應用及效能測試

來源:互聯網
上載者:User

WSGI Server有哪些:


比如 Flask,webpy,Django、CherryPy 都帶著 WSGI server 。當然效能都不好,內建的web server 更多的是測試用途, 線上發布時,則使用高效能的 wsgi server或者是聯合nginx做uwsgi 。


誠如那個WSGI的定義所說的,協議定義了一套介面來實現伺服器端與應用端通訊的正常化或者說是統一化)。這是怎樣的一套介面呢?很簡單,尤其是對於應用端。

源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35U4P-0.png" title="2283144_1319162549AHXr.png" />

神器 Gunicorn是一個Python WSGI UNIX的HTTP伺服器。這是一個預先叉工人模式,從Ruby的獨角獸Unicorn)項目移植。該Gunicorn伺服器與各種Web架構相容,我們只要簡單配置執行,輕量級的資源消耗,以及相當迅速。它的特點是與各個web結合緊密,部署特別方便。 缺點也很多,不支援HTTP 1.1,並發訪問效能不高。


安裝 gunicorn  ~

pip install gunicorn


650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35W118-1.jpg" title="00000.jpg" />


這裡我們說下 gunicorn 的用法

最簡單的運行方式就是:


gunicorn code:application


其中code就是指code.py,application就是那個wsgifunc的名字。


這樣啟動並執行話, gunicorn 預設作為一個監聽 127.0.0.1:8000 的web server,可以在本機通過: http://127.0.0.1:8000 訪問。



如果要通過網路訪問,則需要綁定不同的地址也可以同時設定監聽連接埠):


gunicorn -b 10.2.20.66:8080 code:application#from http://rfyiamcool.blog.51cto.com


在多核伺服器上,為了支援更多的並發訪問並充分利用資源,可以使用更多的 gunicorn 進程:


gunicorn -w 8 code:application


這樣就可以啟動8個進程同時處理HTTP請求,提高系統的使用效率及效能。


另外, gunicorn 預設使用同步阻塞的網路模型(-k sync),對於大並發的訪問可能表現不夠好, 它還支援其它更好的模式,比如:gevent或meinheld。

源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

#  gevent

gunicorn -k gevent code:application

#  meinheld

gunicorn -k egg:meinheld#gunicorn_worker code:application

當然,要使用這兩個東西需要另外安裝,具體請參考各自的文檔。


以上設定還可以通過 -c 參數傳入一個設定檔實現。


gunicorn 的設定檔

[root@66 tmp]# cat gun.confimport osbind = '127.0.0.1:5000'workers = 4backlog = 2048worker_class = "sync"debug = Trueproc_name = 'gunicorn.proc'pidfile = '/tmp/gunicorn.pid'logfile = '/var/log/gunicorn/debug.log'loglevel = 'debug'



python web 一個例子

[root@66 tmp]# cat xiaorui.pyfrom flask import Flaskfrom flask import render_template_stringimport osfrom werkzeug.contrib.fixers import ProxyFixapp = Flask(__name__)@app.route('/')def index():    return "worked!"app.wsgi_app = ProxyFix(app.wsgi_app)if __name__ == '__main__':    app.run()


先跑本身的demo ~

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35WU0-2.jpg" title="ce.jpg" />

源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

結果是:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35Va5-3.jpg" title="ceshi2_副本.jpg" />


結果還算可以~    當然跑的執行個體也簡單~


650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35VL6-4.jpg" style="float:none;" title="2222.jpg" />

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35VV9-5.jpg" style="float:none;" title="33333.jpg" />


cpu的損耗,不小哈~

其次的問題是,flask的web server在壓力下出現回應的錯誤。。。 我以前測試 tornado web.py flask django botto的壓力,讓朋友寫的cc工具做的測試。。。

結果是  tornado確實很牛,然後是flask,接著是web.py,最爛的是django

django本身的抗壓確實讓人蛋疼,還好大家在nginx做負載。

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35Q556-6.jpg" title="444.jpg" />

單一實例測試完了,咱們開始測試 高效能神器 gunicorn 做wsgi

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35T403-7.jpg" title="QQ20130819000222.jpg" />


啟動後會出現:

2013-08-12 21:59:34 [2097] [INFO] Starting gunicorn 17.52013-08-12 21:59:34 [2097] [DEBUG] Arbiter booted2013-08-12 21:59:34 [2097] [INFO] Listening at: http://127.0.0.1:5000 (2097)2013-08-12 21:59:34 [2097] [INFO] Using worker: sync2013-08-12 21:59:34 [2102] [INFO] Booting worker with pid: 21022013-08-12 21:59:34 [2103] [INFO] Booting worker with pid: 21032013-08-12 21:59:34 [2104] [INFO] Booting worker with pid: 21042013-08-12 21:59:34 [2105] [INFO] Booting worker with pid: 2105


我們再來測試下效能~

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35S140-8.jpg" title="444.jpg" />



上次用了6秒左右,這次用gunicorn達到了2.4秒左右。。。。。 這速度對比,已經很明了了~

要是還想提高速度,可以改gun.conf設定檔中的worker數目。


cpu的損耗是平均到各個進程,而不是獨立在flask的web server上


650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35TH5-9.jpg" title="555.jpg" />



現在我們開始測試gevent 作為wsgi 網關介面的實力~


flask的一個demo~

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35U4U-10.jpg" title="QQ20130819004120.jpg" />


gevent wsgi的配置,我先簡單的做下配置。。。。

大家想看執行個體的話,可以去gevent的官網的wsgi的demo   那邊還附有編程的介面。。。


from gevent.wsgi import WSGIServerfrom a import apphttp_server = WSGIServer(('', 11111), app)http_server.serve_forever()


源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

我們開始測試更牛逼的gevent的並發能力 。

服務端:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35QU1-11.jpg" title="6666.jpg" />

用戶端:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35R941-12.jpg" title="8888.jpg" />


看到秒數了吧~    啥也不說了~    大家都懂了~

我們稍微調節一下~

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35WP5-13.jpg" title="1111.jpg" />


事實上, gunicorn 調用 gevent workers 的代碼類似這樣的原理(uwsgi+gevent 也是差不多的做法).


#!/usr/bin/env python# coding:utf-8                                                                                                                                                                              import sysimport os                                                                                                                                                                              import geventimport gevent.monkeyimport gevent.wsgiimport gevent.servergevent.monkey.patch_all()                                                                                                                                                                              import socketimport multiprocessing                                                                                                                                                                              def app(environ, start_response):    start_response('200 OK', [('Content-Type','text/plain')])    yield str(socket.getaddrinfo('xiaorui.cc', 80))                                                                                                                                                                              def handle_signals():    gevent.sleep(sys.maxint)                                                                                                                                                                              if __name__ == '__main__':    listenner = gevent.server._tcp_listener(('', 8002), backlog=500, reuse_addr=True)    for i in xrange(multiprocessing.cpu_count()*2):        server = gevent.wsgi.WSGIServer(listenner, app, log=None)        process = multiprocessing.Process(target=server.serve_forever)        process.start()    handle_signals()


uwsgi現在也支援gevent的方式:


uwsgi --plugins python,gevent --gevent 100 --socket :3031 --module myapp



總之,gunicorn和gevent,或者是gunicorn+gevent的合體 都是很值得嘗試的東西。


源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364


是我推薦的網路架構~ 這個架構和uwsgi的方式很像的,都是在nginx pass_proxy到app的前連接埠,然後用uwsgi或者是gunicorn來協同處理 。


650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1F35U622-14.png" title="wsgi-nginx-gunicorn-supervisor.png" />



server {    listen 80;    server_name xiaorui.cc;                                                                                                                                                                                                                                                                                                                                                                                      root /www/xiaorui;                                                                                                                                                                                                                                                                                                                                                                                      access_log xiaorui/access.log;    error_log xiaorui/error.log;                                                                                                                                                                                                                                                                                                                                                                                      location / {        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;        proxy_set_header Host $http_host;        proxy_redirect off;        if (!-f $request_filename) {            proxy_pass http://127.0.0.1:8000;            break;        }    }




前端Nginx負載,幾個核就跑幾個Gunicorn進程,gunicorn相對後面的app又可以給出幾個進程。

比起uWSGI來說,Gunicorn對於“協程”也就是Gevent的支援會更好更完美。

方便以後業務的擴充和運營精細化。效能上Gunicorn+Gevent不會比uWSGI弱多少,畢竟後者純C能只有這麼點效能也不容易,比起WSGI Server裡面最強的Bjoern而言,Gunicorn也有對應的Meinheld這種利器,況且後者對於HTTP協議的支援比Bjoern更完善。Gevent雖然不是非同步架構裡面效能最好的,但是絕對是最完善的,社區活躍度也非常高,加上方便的monkey_patch,使得大多數應用不用改代碼就能方便地平移過來。這2者結合可以就保證了穩定性,又能有較好效能的組合。


想簡單擴充就用 Gunicorn+Gevent,想麻煩折騰就用nginx 做uwsgi或gunicorn的組合 。


本文出自 “峰雲,就她了。” 部落格,謝絕轉載!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.