學過PHP的都瞭解,php的正式環境部署很是簡單,改幾個文件就OK,用FastCgi方式也是分分鐘的事情。相比起來,Python在web應用上的部署就繁雜的多,主要是工具繁多,主流服務器支持不足。php
在瞭解Python的生產環境部署方式以前,先明確一些概念!很重要html
CGI即通用網關接口(Common Gateway Interface),是外部應用程序(CGI程序)與Web服務器之間的接口標準,是在CGI程序和Web服務器之間傳遞信息的規程。CGI規範容許Web服務器執行外部程序,並將它們的輸出發送給Web瀏覽器,CGI將Web的一組簡單的靜態超媒體文檔變成一個完整的新的交互式媒體。通俗的講CGI就像是一座橋,把網頁和WEB服務器中的執行程序鏈接起來,它把HTML接收的指令傳遞給服務器的執行程序,再把服務器執行程序的結果返還給HTML頁。CGI 的跨平臺性能極佳,幾乎能夠在任何操做系統上實現。python
CGI方式在遇到鏈接請求(用戶請求)先要建立cgi的子進程,激活一個CGI進程,而後處理請求,處理完後結束這個子進程。這就是fork-and-execute模式。因此用cgi方式的服務器有多少鏈接請求就會有多少cgi子進程,子進程反覆加載是cgi性能低下的主要緣由。當用戶請求數量很是多時,會大量擠佔系統的資源如內存,CPU時間等,形成效能低下。web
CGI腳本工做流程:數據庫
python有cgi模塊可支持原生cgi程序apache
FastCGI是一個可伸縮地、高速地在HTTP server和動態腳本語言間通訊的接口。多數流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同時,FastCGI也被許多腳本語言所支持,其中就有Python。FastCGI是從CGI發展改進而來的。傳統CGI接口方式的主要缺點是性能不好,由於每次HTTP服務器遇到動態程序時都須要從新啓動腳本解析器來執行解析,而後結果被返回給HTTP服務器。這在處理高併發訪問時,幾乎是不可用的。FastCGI像是一個常駐(long-live)型的CGI,它能夠一直執行着,只要激活後,不會每次都要花費時間去fork一次(這是CGI最爲人詬病的fork-and-execute 模式)。CGI 就是所謂的短生存期應用程序,FastCGI 就是所謂的長生存期應用程序。因爲 FastCGI 程序並不須要不斷的產生新進程,能夠大大下降服務器的壓力而且產生較高的應用效率。它的速度效率最少要比CGI 技術提升 5 倍以上。它還支持分佈式的運算, 即 FastCGI 程序能夠在網站服務器之外的主機上執行而且接受來自其它網站服務器來的請求。瀏覽器
FastCGI是語言無關的、可伸縮架構的CGI開放擴展,其主要行爲是將CGI解釋器進程保持在內存中並所以得到較高的性能。衆所周知,CGI解釋器的反覆加載是CGI性能低下的主要緣由,若是CGI解釋器保持在內存中並接受FastCGI進程管理器調度,則能夠提供良好的性能、伸縮性、Fail-Over特性等等。FastCGI接口方式採用C/S結構,能夠將HTTP服務器和腳本解析服務器分開,同時在腳本解析服務器上啓動一個或者多個腳本解析守護進程。當HTTP服務器每次遇到動態程序時,能夠將其直接交付給FastCGI進程來執行,而後將獲得的結果返回給瀏覽器。這種方式可讓HTTP服務器專注地處理靜態請求或者將動態腳本服務器的結果返回給客戶端,這在很大程度上提升了整個應用系統的性能。服務器
FastCGI的工做流程:網絡
FastCGI 的特色:架構
Python Web服務器網關接口(Python Web Server Gateway Interface,縮寫爲WSGI)是爲Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口。自從WSGI被開發出來之後,許多其它語言中也出現了相似接口。WSGI是做爲Web服務器與Web應用程序或應用框架之間的一種低級別的接口,以提高可移植Web應用開發的共同點。WSGI是基於現存的CGI標準而設計的。
WSGI區分爲兩個部份:一爲「服務器」或「網關」,另外一爲「應用程序」或「應用框架」。在處理一個WSGI請求時,服務器會爲應用程序提供環境上下文及一個回調函數(Callback Function)。當應用程序完成處理請求後,透過先前的回調函數,將結果回傳給服務器。所謂的 WSGI 中間件同時實現了API的兩方,所以能夠在WSGI服務和WSGI應用之間起調解做用:從WSGI服務器的角度來講,中間件扮演應用程序,而從應用程序的角度來講,中間件扮演服務器。「中間件」組件能夠執行如下功能:
之前,如何選擇合適的Web應用程序框架成爲困擾Python初學者的一個問題,這是由於,通常而言,Web應用框架的選擇將限制可用的Web服務器的選擇,反之亦然。那時的Python應用程序一般是爲CGI,FastCGI,mod_python中的一個而設計,甚至是爲特定Web服務器的自定義的API接口而設計的。WSGI沒有官方的實現, 由於WSGI更像一個協議。只要遵守這些協議,WSGI應用(Application)均可以在任何服務器(Server)上運行, 反之亦然。WSGI就是Python的CGI包裝,相對於Fastcgi是PHP的CGI包裝。
WSGI將 web 組件分爲三類: web服務器,web中間件,web應用程序, wsgi基本處理模式爲 : WSGI Server -> (WSGI Middleware)* -> WSGI Application 。
uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型(type of information),每個uwsgi packet前4byte爲傳輸信息類型描述,它與WSGI相比是兩樣東西。據稱其效率是fcgi的10倍。具體的協議內容請參考:the uwsgi protocol(http://uwsgi-docs.readthedocs.org/en/latest/Protocol.html)
以上四者均可以理解爲協議!協議!協議!實現了這樣的協議,就能夠實現Web服務器與Web應用程序相關聯的web服務!
uWSGI:
uWSGI項目旨在爲部署分佈式集羣的網絡應用開發一套完整的解決方案。uWSGI主要面向web及其標準服務,已經成功的應用於多種不一樣的語言。因爲uWSGI的可擴展架構,它可以被無限制的擴展用來支持更多的平臺和語言。目前,你可使用C,C++和Objective-C來編寫插件。項目名稱中的「WSGI」是爲了向同名的Python Web標準表示感謝,由於WSGI爲該項目開發了第一個插件。uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。uWSGI,既不用wsgi協議也不用FastCGI協議,而是自創了上文說將的uwsgi協議。
uWSGI的主要特色以下:
和uWSGi相似的工具,從rails的部署工具(Unicorn)移植過來的。可是它使用的協議是前文所講的WSGI,這是python2.5時定義的官方標準(PEP 333 ),根紅苗正,並且部署比較簡單,詳細的使用教程請點擊這裏(http://gunicorn.org/)。Gunicorn採用prefork模式,Gunicorn 服務器與各類 Web 框架兼容,只需很是簡單的執行,輕量級的資源消耗,以及至關迅速。它的特色是與 Django 結合緊密,部署特別方便。 缺點也不少,不支持 HTTP 1.1,併發訪問性能不高,與 uWSGI,Gevent 等有必定的性能差距。
1. Gunicorn設計
Gunicorn 是一個 master 進程,spawn 出數個工做進程的 web 服務器。master 進程控制工做進程的產生與消亡,工做進程只須要接受請求而且處理。這樣分離的方式使得 reload 代碼很是方便,也很容易增長或減小工做進程。 工做進程這塊做者給了很大的擴展餘地,它能夠支持不一樣的IO方式,如 Gevent,Sync 同步進程,Asyc 異步進程,Eventlet 等等。master 跟 worker 進程徹底分離,使得 Gunicorn 實質上就是一個控制進程的服務。
2. Gunicorn源碼結構
從 Application.run() 開始,首先初始化配置,從文件讀取,終端讀取等等方式完成 configurate。而後啓動 Arbiter,Arbiter 是實質上的 master 進程的核心,它首先從配置類中讀取並設置,而後初始化信號處理函數,創建 socket。而後就是開始 spawn 工做進程,根據配置的工做進程數進行 spawn。而後就進入了輪詢狀態,收到信號,處理信號而後繼續。這裏喚醒進程的方式是創建一個 PIPE,經過信號處理函數往 pipe 裏 write,而後 master 從 select.select() 中喚醒。
工做進程在 spawn 後,開始初始化,而後一樣對信號進行處理,而且開始輪詢,處理 HTTP 請求,調用 WSGI 的應用端,獲得 resopnse 返回。而後繼續。
Sync 同步進程的好處在於每一個 request 都是分離的,每一個 request 失敗都不會影響其餘 request,但這樣致使了性能上的瓶頸。
Tornado即便一款python 的開發框架,也是一個異步非阻塞的http服務器,它自己的數據產出實現沒有聽從上文所說的一些通用協議,由於自身就是web服務器,因此動態請求就直接經過內部的機制,輸出成用戶所請求的動態內容。若是把它做爲一個單獨服務器,想用它來配合其餘的框架如Flask來部署,則須要採用WSGI協議,Tornado內置了該協議,tornado.wsgi.WSGIContainer。
Python自帶的實現了WSGI協議的的wsgi server。wsgi server能夠理解爲一個符合wsgi規範的web server,接收request請求,封裝一系列環境變量,按照wsgi規範調用註冊的wsgi app,最後將response返回給客戶端。Django的自帶服務器就是它了。
以上均可以理解爲實現!實現!實現!實現了協議的工具!
注:mod_wsgi(apache的模塊)其實也是實現了wsgi協議的一個模塊,如今幾乎不廢棄了,因此也很少說了,感興趣的本身查一下吧。
因此若是你採用Django框架開發了應用以後,想部署到生產環境,確定不能用Django自帶的,能夠用使用uwsgi協議的uWSGI服務器,也能夠採用實現了WSGI協議的gunicorn或者Tornado,亦能夠用FastCGI、CGI模式的Nginx、lighttpd、apache服務器。其餘框架亦如此!明白了這些概念在部署的時候就能夠作到心中有數,各類工具之間的搭配也就「知其然,並知其因此然」了。
在咱們組的項目中有兩種框架Django和Tornado,生產環境也用到了兩種部署方式。uWSGI和Gunicorn:
Django項目用Nginx+uWSGI方式部署,Tornado項目用Nginx+Gunicorn方式部署:
Nginx都做爲負載均衡以及靜態內容轉發。Tornado項目用supervisord來管理Gunicorn,用Gunicorn管理Tornado。衆所周知,因爲Python的GIL存在,因此Python的併發都採用多進程模式,因此咱們部署的方式是一個核心兩個進程。