Gunicorn「綠色獨角獸」是一個被普遍使用的高性能的Python WSGI UNIX HTTP服務器,移植自Ruby的獨角獸(Unicorn )項目,使用pre-fork worker模式,具備使用很是簡單,輕量級的資源消耗,以及高性能等特色。django
Gunicorn 服務器做爲wsgi app的容器,可以與各類Web框架兼容(flask,django等),得益於gevent等技術,使用Gunicorn可以在基本不改變wsgi app代碼的前提下,大幅度提升wsgi app的性能。flask
gunicorn pre-fork worker模型中有一個管理進程以及幾個的工做進程。管理進程:master,工做進程:worker。(如下代碼中爲了方面理解,均去除了一些干擾代碼)服務器
master經過pre-fork的方式建立多個worker:網絡
在worker.init_process()函數中,worker中gunicorn的app對象會去import 咱們的wsgi app。也就是說,每一個woker子進程都會單獨去實例化咱們的wsgi app對象。每一個worker中的swgi app對象是相互獨立、互不干擾的。app
manager維護數量固定的worker:框架
建立完全部的worker後,worker和master各自進入本身的消息循環。
master的事件循環就是收收信號,管理管理worker進程,而worker進程的事件循環就是監聽網絡事件並處理(如新建鏈接,斷開鏈接,處理請求發送響應等等),因此真正的鏈接最終是連到了worker進程上的。(注:有關這種多進程模型的詳細介紹,能夠參考http://blog.csdn.net/largetalk/article/details/7939080)socket
woker有不少種,包括:ggevent、geventlet、gtornado等等。這裏主要分析ggevent。函數
每一個ggevent worker啓動的時候會啓動多個server對象:worker首先爲每一個listener建立一個server對象(注:爲何是一組listener,由於gunicorn能夠綁定一組地址,每一個地址對於一個listener),每一個server對象都有運行在一個單獨的gevent pool對象中。真正等待連接和處理連接的操做是在server對象中進行的。tornado
上面代碼中的server_class其實是一個gevent的WSGI SERVER的子類:性能
須要注意的是構造PyWSGIServer的參數:
這些參數中s是server用來監聽連接的套接字。spawn是gevent的協程池。application便是咱們的wsgi app(通俗點講就是你用 flask 或者 django寫成的app),咱們的app就是經過這種方式交給gunicorn的woker去跑的。 handler_class是gevent的pywsgi.WSGIHandler子類。
當全部server對象建立完畢後,worker須要定時通知manager,不然會被認爲是掛掉了。
這個地方的notify機制設計的比較有趣,每一個worker有個與之對應的tmp file,每次notify的時候去操做一下這個tmp file(好比經過os.fchmod),這個tmp file的last update的時間戳就會更新。而manager則經過檢查每一個worker對應的temp file的last update的時間戳,來判斷這個進程是不是掛掉的。
真正等待連接和處理連接的操做是在gevent的WSGIServer 和 WSGIHandler中進行的。
最後再來看一下gevent的WSGIServer 和 WSGIHandler的主要實現:
WSGIServer 的start函數裏面調用start_accepting來處理到來的連接。在start_accepting裏面獲得接收到的套接字後調用do_handle來處理套接字:
能夠看出,WSGIServer 其實是建立一個協程去處理該套接字,也就是說在WSGIServer 中,一個協程單獨負責一個HTTP連接。協程中運行的self._handle函數其實是調用了WSGIHandler的handle函數來不斷處理http 請求:
在handle函數的循環內部,handle_one_request函數首先讀取HTTP 請求,初始化WSGI環境,而後最終調用run_application函數來處理請求:
在這個地方纔真正的調用了咱們的 app。
總結:gunicorn 會啓動一組 worker進程,全部worker進程公用一組listener,在每一個worker中爲每一個listener創建一個wsgi server。每當有HTTP連接到來時,wsgi server建立一個協程來處理該連接,協程處理該連接的時候,先初始化WSGI環境,而後調用用戶提供的app對象去處理HTTP請求。