相信每一個剛接觸python web開發的同窗,在學習flask、django這些框架的時候,確定會被告知說正式環境部署時,不該該用框架自帶的web服務器啓動對外提供服務,而應該搭配專門的wsgi服務器(uwsgi、gunicorn等)提供服務,爲何?在這套推薦的部署方案中,wsgi服務器和我們使用的框架都各自扮演着什麼角色?本文將盡量用大白話通俗易懂的講清楚。html
首先,先思考一個問題,一個http請求從客戶端發起處處理完成須要進過哪些流程?
服務端的處理能夠分爲兩部分:python
python將這兩部分分開來,即有專門處理客戶端交互的gateway框架。而flask、django這些web框架,則是專門用於進行請求邏輯處理的工做,稱爲application。web
分開後,再看上圖,步驟二、四、5是由gateway框架負責;步驟3由application負責。django
你們都知道,pythoner圈裏個個都是人才,說話又好聽,技術還強的不行,很快就涌現出各類各樣優秀的gateway框架和application框架了,那怎麼能讓這些框架實現「混搭」呢?
咱們能夠規定一個協議,或者說是一個對gateway框架和application的設計要求;規定gateway和application分別都要須要實現什麼方法,方法要怎麼調用;這樣,當市面上出現一個更好的gateway框架時,咱們能夠零成本的將咱們的application跟新的gateway搭配起來。flask
而這套協議,就是wsgi,簡單說,它規定了gateway如何和application交互緩存
1.提供一個接收客戶端請求的服務服務器
Server端實現僞碼併發
class WsgiServer: def __init__(self, host, port, app): def serve_forever(self): # 啓動監聽端口服務,接收請求 def start_response(self, status, headers): # 用於被application調用,設置status和headers ... self.status = status self.headers = headers ... def handle_request(self): # 請求處理函數 environ = { # 請求相關變量 "wsgi.input": self.stdin # request內容 "wsgi.version": self.wsgi_version # wsgi版本信息 ... } iterResult = self.app(environ, self.start_response) # 業務邏輯處理請求,返回可迭代對象 for data in iterResult: self.write(data) # 將數據挨個發送到緩存區 self.send_data() # 將結果返回給客戶端
application的簡單示例app
def application(environ, start_response): # 接收environ、start\_response start_response('200 OK', [('Content-Type', 'text/html')]) # 調用start\_response 用於設置響應狀態和響應頭部信息 return [b'<h1>Hello, web!</h1>'] # 返回一個可迭代對象,做爲響應內容