如何理解Nginx, WSGI, Flask之間的關係

剛轉行互聯網行業,聽到了許多名詞:Flask、Django、WSGI、 Nginx、Apache等等,一直沒法搞清楚這些開源項目之間的關係,直至看到這篇文章後感受醍醐灌頂,如下是轉載的部分,感謝haozlee分享出這篇文章!html


1、概覽

以前對 Nginx,WSGI(或者 uWSGI,uwsgi),Flask(或者 Django),這幾者的關係一存存在疑惑。經過查閱了些資料,總算把它們的關係理清了。python

總括來講,客戶端從發送一個 HTTP 請求到 Flask 處理請求,分別通過了 web服務器層,WSGI層,web框架層,這三個層次。不一樣的層次其做用也不一樣,下面簡要介紹各層的做用。web

圖片描述
圖1:web服務器,web框架與 WSGI 的三層關係編程

2、 各層做用

一、Web服務器層flask

對於傳統的客戶端 - 服務器架構,其請求的處理過程是,客戶端向服務器發送請求,服務器接收請求並處理請求,而後給客戶端返回響應。在這個過程當中,服務器的做用是:
(1)、接收請求
(2)、處理請求
(3)、返回響應服務器

Web服務器是一類特殊的服務器,其做用是主要是接收 HTTP 請求並返回響應。提起 web服務器你們都不會陌生,常見的 web服務器有 Nginx,Apache,IIS等。在上圖1的三層結構中,web服務器是最早接收用戶請求的,並將響應結果返回給用戶。架構

二、Web框架層app

Web框架的做用主要是方便咱們開發 web應用程序,HTTP請求的動態數據就是由 web框架層來提供的。常見的 web框架有Flask,Django等,咱們以 Flask 框架爲例子,展現 web框架的做用:框架

from flask import Flask
    
    app = Flask(__name__)
    @app.route('/hello')
    def hello_world():
        return 'Hello World!'
            
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080)

以上簡單的幾行代碼,就建立了一個 web應用程序對象 app。app 監聽機器全部 ip 的 8080 端口,接受用戶的請求鏈接。咱們知道,HTTP 協議使用 URL 來定位資源,上面的程序會將路徑 /hello 的請求交由 hello_world 方法處理,hello_world 返回 ‘Hello World!’ 字符串。對於 web框架的使用者來講,他們並不關心如何接收 HTTP 請求,也不關心如何將請求路由到具體方法處理並將響應結果返回給用戶。Web框架的使用者在大部分狀況下,只須要關心如何實現業務的邏輯便可。ui

三、WSGI層

WSGI 不是服務器,也不是用於與程序交互的API,更不是真實的代碼,WSGI 只是一種接口,它只適用於 Python 語言,其全稱爲 Web Server Gateway Interface,定義了 web服務器和 web應用之間的接口規範。也就是說,只要 web服務器和 web應用都遵照WSGI協議,那麼 web服務器和 web應用就能夠隨意的組合。

下面的代碼展現了 web服務器是如何與 web應用組合在一塊兒的。

def application(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b"Hello World"]

方法 application由 web服務器調用,參數env,start_response 由 web服務器實現並傳入。其中,env是一個字典,包含了相似 HTTP_HOST,HOST_USER_AGENT,SERVER_PROTOCO 等環境變量。start_response則是一個方法,該方法接受兩個參數,分別是status,response_headers。application方法的主要做用是,設置 http 響應的狀態碼和 Content-Type 等頭部信息,並返回響應的具體結果。

上述代碼就是一個完整的 WSGI 應用,當一個支持 WSGI 的 web服務器接收到客戶端的請求後,便會調用這個 application 方法。WSGI 層並不須要關心env,start_response 這兩個變量是如何實現的,就像在 application 裏面所作的,直接使用這兩個變量便可。

值得指出的是,WSGI 是一種協議,須要區分幾個相近的名詞:
(1)、uwsgi
同 wsgi 同樣也是一種協議,uWSGI服務器正是使用了 uwsgi 協議
(2)、uWSGI
實現了 uwsgi 和 WSGI 兩種協議的web服務器。注意 uWSGI 本質上也是一種 web服務器,處於上面描述的三層結構中的 web服務器層。
(3)、CGI
通用網關接口,並不限於 Python 語言,定義了 web服務器是如何向客戶端提供動態的內容。例如,規定了客戶端如何將參數傳遞給 web服務器,web服務器如何將參數傳遞給 web應用,web應用如何將它的輸出如何發送給客戶端,等等。

生產環境下的 web應用都不使用 CGI 了,CGI進程(相似 Python 解釋器)針對每一個請求建立,用完就拋棄,效率低下。WSGI 正是爲了替代 CGI 而出現的。
說到這,咱們基本理清了 WSGI 在 web服務器與 web框架之間做用:WSGI 就像一條紐帶,將 web服務器與 web框架鏈接起來。回到本文的題目,Nginx 屬於一種 web服務器,Flask屬於一種 web框架,所以,WSGI 與 Nginx、Flask 的做用就不明而喻了。

3、結語

最後以 Nginx,WSGI,Flask 之間的對話結束本文。

Nginx:Hey,WSGI,我剛收到了一個請求,我須要你做些準備,而後由Flask來處理這個請求。
WSGI:OK,Nginx。我會設置好環境變量,而後將這個請求傳遞給Flask處理。
Flask:Thanks WSGI!給我一些時間,我將會把請求的響應返回給你。
WSGI:Alright,那我等你。
Flask:Okay,我完成了,這裏是請求的響應結果,請求把結果傳遞給Nginx。
WSGI:Good job!Nginx,這裏是響應結果,已經按照要求給你傳遞回來了。
Nginx:Cool,我收到了,我把響應結果返回給客戶端。你們合做愉快~

4、參考資料

(1)、http://hackerxu.com/2015/05/1...
(2)、https://www.quora.com/What-ar...
(3)、https://en.wikipedia.org/wiki...
(4)、http://flask.pocoo.org/docs/0...
(5)、http://stackoverflow.com/ques...
(6)、https://www.python.org/dev/pe... (7)、《Python核心編程(第3版)》Wesley Chun著

相關文章
相關標籤/搜索