Python Web開發中,WSGI協議的作用和實現原理詳解


首先理解下面三個概念:

WSGI:全稱是Web Server Gateway Interface,WSGI不是服務器,python模塊,框架,API或者任何軟件,只是一種規范,描述web server如何與web application通信的規范。

uwsgi:與WSGI一樣是一種協議,是uWSGI服務器的獨占協議,用於定義傳輸信息的類型(type of information),每一個uwsgi packet前4byte為傳輸信息類型的描述,與WSGI協議是兩種東西,據說該協議是fcgi協議的10倍快。

uWSGI:是一個web服務器,實現了WSGI協議、uwsgi協議、http協議等。

 

WSGI協議主要包括server和application兩部分:

其中application部分:

示例代碼:

def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-Type', 'text/html')]
    # application內部調用start_response
    start_response(status, response_headers)
    
    # 解析environ信息,業務邏輯處理后,返回對應的響應信息(下面代碼只是模擬業務處理)
    file_name = environ['PATH_INFO']
    if file_name == "/index.py":
        return index(file_name)
    elif file_name == "/center.py":
        return center(file_name)
    else:
        return 'Hello world a simple WSGI application!'

 

有了WSGI,我們在框架中只關心如何從environ這個dict(wgsi規定傳過來一個字典)對象拿到HTTP請求信息,然后構造HTML,通過start_response()發送Header,最后返回Body。

整個application()函數本身沒有涉及到任何解析HTTP的部分。 也就是說,底層代碼不需要我們自己編寫,我們只負責業務邏輯部分即可。

但是我們想一下,這個application()函數怎么調用?如果我們自己調用,兩個參數environ和start_response我們沒法提供,返回的str也沒法發給瀏覽器。

截取server端部分代碼實例如下:

          # 重點關注邏輯
                # 准備一個字典,里面存放需要傳遞給web框架的數據
                env = dict()
                # ----------更新---------
                env['PATH_INFO'] = file_name  # 例如 index.py(模擬請求信息)
                
                # 重點關注邏輯
                # 服務器調用框架中實現的application函數,並將包含請求信息的字典和獲取響應頭的函數傳入
                response_body = self.application(env, self.start_response)
​
                
                # 合並header和body(響應客戶端的請求,這個邏輯不用關注)
                response_header = "HTTP/1.1 {status}\r\n".format(status=self.headers[0])
                response_header += "Content-Type: text/html; charset=utf-8\r\n"
                response_header += "Content-Length: %d\r\n" % len(response_body.encode("utf-8"))
                for temp_head in self.headers[1]:
                    response_header += "{0}:{1}\r\n".format(*temp_head)
​
                response = response_header + "\r\n"
                response += response_body
​
                client_socket.send(response.encode('utf-8'))
​
    # 重點關注邏輯
    # server端實現了start_response函數的定義
    def start_response(self, status, headers):
        """這個方法,會在 web框架中被默認調用"""
        response_header_default = [
            ("Data", time.time()),
            ("Server", "ItCast-python mini web server")
        ]
​
        # 將狀態碼/相應頭信息存儲起來
        # [字符串, [xxxxx, xxx2]]
        self.headers = [status, response_header_default + headers]

 

這段代碼,是在客戶端請求動態資源時啟動,即服務器需要向后端框架請求資源。代碼解析已在代碼中注釋。

所以我們基本可以獲得如下結論:

要實現WSGI協議,必須同時實現web server端和web application端

當前運行在WSGI協議之上的web框架有Torando,Flask,Django等

比較常用的WSGI協議服務器有:uWSGI,gunicorn等

1、框架需要實現WSGI協議,例如:Flask,Django等

2、environ 和 start_response 由 http server 提供並實現

3、environ 變量是包含了請求信息的字典

4、Application 內部在返回前調用 start_response

5、application()函數必須由WSGI服務器來調用

server要履行的任務:

1、接收HTTP請求

2、解析HTTP請求

3、准備 environ請求參數

4、定義 start_response 函數

5、組裝響應頭和相應體返回給客戶端

application要履行的責任:

1、解析服務器發來的請求信息

2、根據請求信息,進行業務處理

3、返回所需要的數據

至此,您應該對WSGI有了一定的了解吧。

擴展閱讀:

目前一些主要的實現了WSGI協議的服務器:

gunicorn

Gunicorn(從Ruby下面的Unicorn發展而來):依賴Nginx的代理行為,同Nginx進行功能上的分離。由於不需要直接處理用戶來的請求(都被Nginx先處理),Gunicorn不需要完成相關的功能,其內部邏輯非常簡單:接受從Nginx來的動態請求,處理完之后返回給Nginx,由后者返回給用戶。

由於功能定位很明確,Gunicorn得以用純Python開發:大大縮短了開發時間的同時,性能上也不會很掉鏈子。同時,它也可以配合Nginx的代理之外的別的Proxy模塊工作,其配置也相應比較簡單。

配置上的簡單,大概是它流行的最大的原因。

uWSGI

因為使用C語言開發,會和底層接觸的更好,配置也是比較方便,目前和gunicorn兩個算是部署時的唯二之選。

以下是通常的配置文件

fcgi

不多說,用的少。

bjoern

Python WSGI界最牛逼性能的Server其中一個是bjoern,純C,小於1000行代碼,就是看不慣uWSGI的冗余自寫的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM