天天看點

python中web伺服器和web架構之間的規範 小白深度了解WSGI

      怎樣在你剛建立的Web伺服器上運作一個Django應用和Flask應用,如何不做任何改變而适應不同的Web架構那?

      在以前,選擇Python web架構會受制于可用的web伺服器,反之亦然。如果架構和可以協同工作,豈不更好嗎?

      當要把一個伺服器和一個架構結合起來時,有可能會發現他們并不是被設計成協同工作的。

      那麼,怎麼在不修改伺服器和架構代碼的前提下而確定可以在多個架構下運作web伺服器那?答案就是:

      Python Web Server Gateway Interface(簡稱WSGI)

      WSGI允許開發者将選擇web架構和web伺服器分開,可以混合比對web伺服器和web架構,選擇一個适合的配對,

比如,可以在Gunicorn或者Nginx/uWSGI或者Waitress上運作Django,Flask,或Pyramid,真正的混合比對,得益于

WSGI同時支援伺服器和架構:

python中web伺服器和web架構之間的規範 小白深度了解WSGI

Web伺服器必須具備WSGI接口,所有的現代Python Web架構都已具備WSGI接口,它讓你不對代碼作修改

就能使伺服器和特定的Web架構協同工作。

WSGI由Web伺服器支援,而Web架構允許你選擇适合自己的配對,但它同樣對于伺服器和架構開發者提供

便利,使他們可以專注于自己偏愛的領域和專長而不至于互相牽制。其他語言也有類似接口:java有Servlet API

,Ruby有Rack等。

當時自己學web架構和web伺服器之間遵循的規範WSGI的時候真是一臉懵逼,兩個之間函數調來調去,暈

暈的其實當真正知道了web架構能提供什麼,web伺服器需要什麼,把他們之間的關系理理清楚問題就會感覺很

清晰。

下面就一起來了解下把!

首先,我們了解以下,用戶端,web伺服器,web架構他們之間的大概的關系脈絡。

python中web伺服器和web架構之間的規範 小白深度了解WSGI

從上圖中看出,先總結下沒有web架構時,最簡單的Client和Server之間的資料收發過程:

1.Client(浏覽器)端像伺服器發起連結請求,通過和Server三次握手建立連接配接,三次握手成功後,浏覽器發起http請求,是以http協定的格式把請求發送過來。

2.web伺服器讀取從浏覽器發送過來的http的請求,分析浏覽器請求的哪個檔案,把檔案的内容讀取出來,加載到程式中去接下來通過http的方式給浏覽器(用戶端)回過去。

python中web伺服器和web架構之間的規範 小白深度了解WSGI

如果是長連結,并不會進行四次揮手,而是用的同一個連結收發資料。

總結:以上是之前浏覽器通路浏覽器的大體的流程,收發資料,處理資料都是由web伺服器自己完成。缺點就是web伺服器的功能太亂了,什麼都要由自己完成耦合性太強了,一個web伺服器幹了自己本來不應該幹的工作。其實像用人一樣,應該把人安排在他最擅長的崗位,什麼都做反而做不好,術業有專攻,每個人都有自己的強項,并且也會為此付出自己所有的興趣,這樣才能做好 。是以,為了完成給web伺服器,減壓,也算是一定意義上的解耦合,web架構就要上場了。

web伺服器應該做的是:接收用戶端的連結,然後把最基本的東西傳遞到web應用程式架構中,他們之間的傳遞過程就要通過WSGI來完成他們之間的和諧連接配接。以下文章會詳細講解WSGI具體實作過程。web應用程式架構把web伺服器所要的東西處理完之後,然後傳回給web伺服器,最後由web伺服器在轉發給浏覽器,這樣做就分工明确了,每一個子產品有問題隻修改其中的一個子產品就行了。

python中web伺服器和web架構之間的規範 小白深度了解WSGI

小總結:一般在開發中,是不需要自己寫伺服器的,自己寫的伺服器一般功能不完善,而且bug也非常多,都是用别人寫好的伺服器,web伺服器可能是c或者c++寫的,内功不深厚者也改不動。

大體的過程我們已經了解了,下面繼續了解解耦之後的過程。

解耦之後,當浏覽器請求之後,web伺服器要通過web應用程式架構為其提供需要給浏覽器發送的header(http頭資訊)和body(http尾資訊)。那麼想要真正的讓web伺服器和web架構分開,完成資料的正确傳遞,就需要他們之間遵循某種協定。 補充:頭資訊和尾資訊 HTTP響應分為Header和Body兩部分(Body是可選項),HTTP響應中的Header最重要的幾行如下: 1.HTTP/1.1 200 OK 200表示一個成功的響應,後面的OK是說明,如果傳回的不是200,那麼往往有其他的功能,例如: 失敗的響應有404 Not Found:網頁不存在 500 Internal Server Error:伺服器内部出錯 等等 2. Content-Type: text/html Content-Type訓示響應的内容,這裡是text/html表示HTML網頁。

浏覽器就是依靠Content-Type來判斷響應的内容是網頁還是圖檔,是視訊還是音樂。浏覽器并不靠URL來判斷響應的内容,是以,即使URL是http://www.baidu.com/meimei.jpg,它也不一定就是圖檔。

HTTP響應的Body就是HTML源碼,我們在浏覽器菜單欄選擇“試圖”,“開發者”,“檢視網頁源碼”就可以在浏覽器中直接檢視HTML源碼: WSGI(web伺服器網關接口)協定引出: 由web伺服器調用應用程式架構中的函數,首先要讓web伺服器知道web應用程式架構中web伺服器需要調用的函數的名字,比如在web架構中定義了一個app函數,這個函數的目的就是為了把web伺服器想要的資料通過這個函數傳遞給web伺服器。要想完成這個過程,他們之間就需要遵循WSGI協定。 WSGI過程: 由web伺服器調用web應用程式架構中的函數,這個函數裡邊可以完成資料的讀取等操作,讀出來之後把資料傳遞給伺服器。web伺服器調用app函數的時候一共傳兩個值給這個函數,第一個值是傳遞一個字典,第二個值就是函數的引用,假如說在伺服器裡邊定義了一個函數,名字叫A,在調用app函數的時候,把A當作實參傳遞過去(補充,一個變量接收了一個函數的引用,那麼這個變量就可以直接調用這個函數)。然後由web應用程式去調用A這個函數,通過傳過來的A的函數的引用,當調用這個A函數的時候把header設定好,在執行A函數之前web伺服器不管以什麼樣的方式都要把header儲存起來。當A函數執行完之後又回到了web應用程式架構,然後通過return的方式把body傳回給web伺服器。 到現在為止,web伺服器已經有了從web應用程式架構接收到的header和body,通過稍微的處理,然後send發送,然後通過web伺服器發送給浏覽器。

看完了上邊的了解過程還是沒明白的兄弟姐妹,下面我們通過最簡單的web_server和最簡單的web_app(web應用程式架構): 簡單的my_web應用程式架構

python中web伺服器和web架構之間的規範 小白深度了解WSGI

     把web應用程式架構中函數的引用傳遞到web伺服器,以供調用:

python中web伺服器和web架構之間的規範 小白深度了解WSGI

       在web應用程式中調用的web伺服器的函數,傳回來頭(header)資訊:

python中web伺服器和web架構之間的規範 小白深度了解WSGI

      在web_Server中調用web架構中的app函數來傳回尾(body)資訊:

python中web伺服器和web架構之間的規範 小白深度了解WSGI

以上代碼分析:

頭資訊的傳遞:

web_server伺服器通過調用web架構中的app(env, self.set_response_headers),把定義的字典env,和伺服器中函數的引用(這個函數的引用為了接收頭資訊)當作實參傳遞給web架構中的app函數。在web伺服器中,定義函數set_response_headers(self, status, headers):這個函數用兩個形參來接收web架構調用這個函數的時候傳遞過來的實參,web架構通過調用web伺服器傳遞過來的函數的引用,start_response(status, response_headers),把web伺服器需要用的頭資訊當作實參傳遞過去,然後web伺服器,通過定義了一個清單來儲存web架構傳遞過來頭資訊。因為如果不用清單或者其他方法來儲存傳過來的頭資訊,資訊會随着函數調用的結束而消失,為了之後繼續使用,是以要把這個輾轉多次得到的頭資訊好好儲存了。 尾部資訊的傳遞相對來說就容易了解了:

随着self.app調用的結束,通過return傳回來了body資訊,找個變量response_body來接收。此時伺服器就有了頭資訊和body資訊。接下來就把傳過來的資訊稍微整理發送給浏覽器即可,這樣想要發送什麼樣的東西隻需要在web應用程式架構中添加想要發送的内容,然後通過return傳回給Server伺服器就行了。 希望這篇文章能給與更多人的幫助,文中有什麼不足的地方,可以私信我指出,有什麼不懂的地方也可以問我,我們一起交流,一起進步。