圖1:web服務器,web框架與 WSGI 的三層關系
Web服務器層
對於傳統的客戶端 – 服務器架構,其請求的處理過程是,客戶端向服務器發送請求,服務器接收請求並處理請求,然後給客戶端返回響應。在這個過程中,服務器的作用是:
接收請求
處理請求
返回響應
Web服務器是壹類特殊的服務器,其作用是主要是接收 HTTP 請求並返回響應。提起 web服務器大家都不會陌生,常見的 web服務器有 Nginx,Apache,IIS等。在上圖1的三層結構中,web服務器是最先接收用戶請求的,並將響應結果返回給用戶。
Web框架層
Web框架的作用主要是方便我們開發 web應用程序,HTTP請求的動態數據就是由 web框架層來提供的。常見的 web框架有Flask,Django等,我們以 Flask 框架為例子,展示 web框架的作用:
Python
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)
1
2
3
4
5
6
7
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框架的使用者在大部分情況下,只需要關心如何實現業務的邏輯即可。
WSGI層
WSGI 不是服務器,也不是用於與程序交互的API,更不是真實的代碼,WSGI 只是壹種接口,它只適用於 Python 語言,其全稱為
Web Server Gateway Interface,定義了 web服務器和 web應用之間的接口規範。也就是說,只要 web服務器和
web應用都遵守WSGI協議,那麽 web服務器和 web應用就可以隨意的組合。
下面的代碼展示了 web服務器是如何與 web應用組合在壹起的
Python
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World"]
1
2
3
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World"]
方法 application由 web服務器調用,參數 env, start_response 由 web服務器實現並傳入。其中,
env是壹個字典,包含了類似 HTTPHOST,HOSTUSERAGENT,SERVERPROTOCO 等環境變量。
start_response則是壹個方法,該方法接受兩個參數,分別是 status, response_headers。
application方法的主要作用是,設置 http 響應的狀態碼和 Content-Type 等頭部信息,並返回響應的具體結果。
上述代碼就是壹個完整的 WSGI 應用,當壹個支持 WSGI 的 web服務器接收到客戶端的請求後,便會調用這個 application
方法。WSGI 層並不需要關心 env, start_response 這兩個變量是如何實現的,就像在 application
裏面所做的,直接使用這兩個變量即可。
值得指出的是,WSGI 是壹種協議,需要區分幾個相近的名詞:
uwsgi:同 wsgi 壹樣也是壹種協議,uWSGI服務器正是使用了 uwsgi 協議
uWSGI:實現了 uwsgi 和 WSGI 兩種協議的web服務器。註意 uWSGI 本質上也是壹種 web服務器,處於上面描述的三層結構中的 web服務器層。
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 的作用就不明而喻了。
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,我收到了,我把響應結果返回給客戶端。大家合作愉快~