http://www.nowamagic.net/academy/detail/1330316
http://www.tuicool.com/articles/aiami2
Gunicorn(gunicorn.org)是一個 Python WSGI UNIX 的 HTTP 服務器。這是一個預先叉工人模式,從 Ruby 的獨角獸(Unicorn)項目移植。該 Gunicorn 服務器與各種 Web 框架兼容,只需非常簡單的執行,輕量級的資源消耗,以及相當迅速。它的特點是與 Django 結合緊密,部署特別方便。 缺點也很多,不支持 HTTP 1.1,并發訪問性能不高,與 uWSGI,Gevent 等有一定的性能差距。具體比較可以參看列舉一些常見的Python HTTP服務器。
但其實Gunicorn從設計上就不是充當直接從外界接受請求的服務器,作者在 FAQ 里明確提到,Gunicorn 應該是在 Nginx 等服務器后面支持應用請求的。
- Gunicorn設計
Gunicorn 是一個 master進程,spawn 出數個工作進程的 web 服務器。master 進程控制工作進程的產生與消亡,工作進程只需要接受請求并且處理。這樣分離的方式使得 reload 代碼非常方便,也很容易增加或減少工作進程。 工作進程這塊作者給了很大的擴展余地,它可以支持不同的IO方式,如 Gevent,Sync 同步進程,Asyc 異步進程,Eventlet 等等。master 跟 worker 進程完全分離,使得 Gunicorn 實質上就是一個控制進程的服務。
- Gunicorn源碼結構
從 Application.run() 開始,首先初始化配置,從文件讀取,終端讀取等等方式完成 configurate。然后啟動
Arbiter,Arbiter 是實質上的 master 進程的核心,它首先從配置類中讀取并設置,然后初始化信號處理函數,建立
socket。然后就是開始 spawn 工作進程,根據配置的工作進程數進行
spawn。然后就進入了輪詢狀態,收到信號,處理信號然后繼續。這里喚醒進程的方式是建立一個 PIPE,通過信號處理函數往 pipe 里
write,然后 master 從 select.select() 中喚醒。
工作進程在 spawn 后,開始初始化,然后同樣對信號進行處理,并且開始輪詢,處理 HTTP 請求,調用 WSGI 的應用端,得到 resopnse 返回。然后繼續。
Sync 同步進程的好處在于每個 request 都是分離的,每個 request 失敗都不會影響其他 request,但這樣導致了性能上的瓶頸。
gunicorn -w 2 -b 0.0.0.0:8549 app:app # 起兩個并發進程,進程失敗以后會重新拉起
- 配合gevent
另外, gunicorn 默認使用同步阻塞的網絡模型(-k sync),對于大并發的訪問可能表現不夠好, 它還支持其它更好的模式,比如:gevent或meinheld。
gevent是一個基于libev的并發庫。它為各種并發和網絡相關的任務提供了整潔的API。gunicorn對于“協程”也就是Gevent的支持非常好。
gevent程序員指南:gevnet指南
gevent.monkey介紹詳見:關于gevent monkey。
gunicorn -k gevent code:application
- 指定配置文件
以上設置還可以通過 -c 參數傳入一個配置文件實現。
gunicorn -c gun.conf code:application
gunicorn -c gun.py hello:app
配置 gun.conf
import os
bind = '127.0.0.1:5000'
workers = 4
backlog = 2048
worker_class = "gevent" #sync, gevent,meinheld
debug = True
proc_name = 'gunicorn.proc'
pidfile = '/tmp/gunicorn.pid'
logfile = '/var/log/gunicorn/debug.log'
loglevel = 'debug'
配置 gun.py
import os
import gevent.monkey
gevent.monkey.patch_all()
import multiprocessing
debug = True
loglevel = 'debug'
bind = '0.0.0.0:8800'
pidfile = 'log/gunicorn.pid'
logfile = 'log/debug.log'
#啟動的進程數
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'gunicorn.workers.ggevent.GeventWorker'
x_forwarded_for_header = 'X-FORWARDED-FOR'
Gunicorn 框架圖: