Num01-->瀏覽器動(dòng)態(tài)請(qǐng)求頁(yè)面流程圖
以上圖片就是整個(gè)瀏覽器動(dòng)態(tài)請(qǐng)求服務(wù)器的全過程户敬。
Num02-->什么是WSGI卷玉?
WSGI统刮,全稱 Web Server Gateway Interface嵌言,或者 Python Web Server Gateway Interface 椭微,是為 Python 語言定義的 Web 服務(wù)器和 Web 應(yīng)用程序或框架之間的一種簡(jiǎn)單而通用的接口。
WSGI 的官方定義是之众,the Python Web Server Gateway Interface拙毫。從名字就可以看出來,這東西是一個(gè)Gateway棺禾,也就是網(wǎng)關(guān)缀蹄。網(wǎng)關(guān)的作用就是在協(xié)議之間進(jìn)行轉(zhuǎn)換。
WSGI 是作為 Web 服務(wù)器與 Web 應(yīng)用程序或應(yīng)用框架之間的一種低級(jí)別的接口膘婶,以提升可移植 Web 應(yīng)用開發(fā)的共同點(diǎn)缺前。WSGI 是基于現(xiàn)存的 CGI 標(biāo)準(zhǔn)而設(shè)計(jì)的。
很多框架都自帶了 WSGI server 悬襟,比如 Flask衅码,webpy,Django脊岳、CherryPy等等逝段。當(dāng)然性能都不好,自帶的 web server 更多的是測(cè)試用途割捅,發(fā)布時(shí)則使用生產(chǎn)環(huán)境的 WSGI server或者是聯(lián)合 nginx 做 uwsgi 奶躯。
一句話總結(jié)就是:WSGI就像是一座橋梁,一邊連著web服務(wù)器亿驾,另一邊連著用戶的application應(yīng)用嘹黔。但是呢,這個(gè)橋的功能很弱莫瞬,有時(shí)候還需要?jiǎng)e的橋來幫忙才能進(jìn)行處理儡蔓。
Num03-->WSGI的作用
WSGI有兩方:“服務(wù)器”或“網(wǎng)關(guān)”一方郭蕉,以及“應(yīng)用程序”或“應(yīng)用框架”一方。服務(wù)方調(diào)用應(yīng)用方喂江,提供環(huán)境信息召锈,以及一個(gè)回調(diào)函數(shù)(提供給應(yīng)用程序用來將消息頭傳遞給服務(wù)器方),并接收Web內(nèi)容作為返回值开呐。
所謂的 WSGI中間件同時(shí)實(shí)現(xiàn)了API的兩方烟勋,因此可以在WSGI服務(wù)和WSGI應(yīng)用之間起調(diào)解作用:從WSGI服務(wù)器的角度來說规求,中間件扮演應(yīng)用程序筐付,而從應(yīng)用程序的角度來說,中間件扮演服務(wù)器阻肿。
“中間件”組件可以執(zhí)行以下功能:
1瓦戚,重寫環(huán)境變量后,根據(jù)目標(biāo)URL丛塌,將請(qǐng)求消息路由到不同的應(yīng)用對(duì)象较解。
2,允許在一個(gè)進(jìn)程中同時(shí)運(yùn)行多個(gè)應(yīng)用程序或應(yīng)用框架赴邻。
3印衔,負(fù)載均衡和遠(yuǎn)程處理,通過在網(wǎng)絡(luò)上轉(zhuǎn)發(fā)請(qǐng)求和響應(yīng)消息姥敛。
4奸焙,進(jìn)行內(nèi)容后處理,例如應(yīng)用XSLT樣式表彤敛。
Num04-->WSGI Application
可調(diào)用對(duì)象是指:函數(shù)与帆、方法、類或者帶有callable方法的實(shí)例墨榄。
可調(diào)用對(duì)象都可以作為the application object
WSGI協(xié)議要求:
the application object接受兩個(gè)參數(shù)且可以被多次調(diào)用
這兩個(gè)參數(shù)分別為:
參數(shù)一:environ:是一個(gè)CGI式的字典玄糟;
參數(shù)二:start_response:是一個(gè)回調(diào)函數(shù):application用來向server傳遞http狀態(tài)碼/消息/http頭
注意:協(xié)議要求可調(diào)用對(duì)象必須將響應(yīng)體封裝成一個(gè)可迭代的strings返回。
# the application object. 可以使用其他名字,
# 但是在使用mod_wsgi 時(shí)必須為 "application"
def application( environ, start_response):
# 構(gòu)造響應(yīng)體袄秩,以可迭代字符串形式封裝
response_body = 'The request method was %s' % environ['REQUEST_METHOD']
# HTTP 響應(yīng)碼及消息
status = '200 OK'
# 提供給客戶端的響應(yīng)頭.
# 封裝成list of tuple pairs 的形式:
# 格式要求:[(Header name, Header value)].
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))]
# 將響應(yīng)碼/消息及響應(yīng)頭通過傳入的start_reponse回調(diào)函數(shù)返回給server
start_response(status, response_headers)
# 響應(yīng)體作為返回值返回
# 注意這里被封裝到了list中.
return [response_body]
Num05-->WSGI Server
wsgi server可以理解為一個(gè)符合wsgi規(guī)范的web server阵翎,接收request請(qǐng)求,封裝一系列環(huán)境變量之剧,按照wsgi規(guī)范調(diào)用注冊(cè)的wsgi app郭卫,最后將response返回給客戶端。
WSGI server必須要調(diào)用application猪狈,同時(shí)箱沦,從application的協(xié)議要求可知:
第一: WSGI server必須向application提供環(huán)境參數(shù),因此雇庙,自身也必須能夠獲取環(huán)境參數(shù)谓形。
第二: WSGI server接收application的返回值作為響應(yīng)體灶伊。
#最簡(jiǎn)單的WSGI server為Python自帶的wsgiref.simple_server
from wsgiref.simple_server import make_server
srv = make_server('localhost', 8080, fuc)
srv.serve_forever()
wsgi server的基本工作流程:
1,服務(wù)器創(chuàng)建socket寒跳,監(jiān)聽端口聘萨,等待客戶端連接。
2童太,當(dāng)有請(qǐng)求來時(shí)米辐,服務(wù)器解析客戶端信息放到環(huán)境變量environ中,并調(diào)用綁定的handler來處理請(qǐng)求书释。
3翘贮,handler解析這個(gè)http請(qǐng)求,將請(qǐng)求信息例如method爆惧,path等放到environ中狸页。
4,wsgi handler再將一些服務(wù)器端信息也放到environ中扯再,最后服務(wù)器信息芍耘,客戶端信息,本次請(qǐng)求信息全部都保存到了環(huán)境變量environ中熄阻。
5斋竞,wsgi handler 調(diào)用注冊(cè)的wsgi app,并將environ和回調(diào)函數(shù)傳給wsgi app
6秃殉,wsgi app 將reponse header/status/body 回傳給wsgi handler
最終handler還是通過socket將response信息塞回給客戶端坝初。
Num06-->WSGI MiddleWare
假設(shè)一個(gè)符合application標(biāo)準(zhǔn)的可調(diào)用對(duì)象,它接受可調(diào)用對(duì)象作為參數(shù)复濒,返回一個(gè)可調(diào)用對(duì)象的對(duì)象脖卖。
那么對(duì)于server來說,它是一個(gè)符合標(biāo)準(zhǔn)的可調(diào)用對(duì)象巧颈,因此是application畦木。
而對(duì)于application來說,它可以調(diào)用application砸泛,因此是server十籍。
這樣的可調(diào)用對(duì)象稱為middleware。
#一個(gè)路由的例子實(shí)例如下:
import re
# 這是一個(gè)標(biāo)準(zhǔn)的index application object
def index(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ['index page']
# 這是一個(gè)標(biāo)準(zhǔn)的hello application object
def hello(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ['hello page']
# 這是一個(gè)標(biāo)準(zhǔn)的not _found application object
def not_found(environ, start_response):
start_response('404 NOT FOUND', [('Content-Type', 'text/plain')])
return ['Not Found Page']
# map urls to functions
urls = [
(r'^$', index),
(r'hello/?$', hello)
]
# 這是一個(gè)middleware
# 根據(jù)不同的route返回不同的application object
def application(environ, start_response):
path = environ.get('PATH_INFO', '').lstrip('/')
for regex, callback in urls:
match = re.search(regex, path)
if match is not None:
本文參考資料如下:
http://www.jb51.net/article/65875.htm