python wsgi 簡介

發表於2017-02-15

基礎知識

Python 知識

  • iterator 和 generator
  • 函式的高階用法:巢狀函式,作為引數傳遞等等
  • 瞭解 decorator 會對理解 wsgi 有很大的幫助
  • python 的 callable 概念
  • classmethod 和 staticmethod 的概念
  • web 程式設計的基礎

HTTP 基礎

http

對於 web 應用程式來說,最基本的概念就是客戶端傳送請求(request),收到伺服器端的響應(response)。

下面是簡單的 HTTP 請求:

內容包括了 method、 url、 protocol version 以及頭部的資訊。而 HTTP 響應(不包括資料)可能是如下的內容:

實際生產中,python 程式是放在伺服器的 http server(比如 apache, nginx 等)上的。現在的問題是 伺服器程式怎麼把接受到的請求傳遞給 python 呢,怎麼在網路的資料流和 python 的結構體之間轉換呢?這就是 wsgi 做的事情:一套關於程式端和伺服器端的規範,或者說統一的介面。

WSGI

我們先看一下面向 http 的 python 程式需要關心哪些內容:

  • 請求
    • 請求的方法 method
    • 請求的地址 url
    • 請求的內容
    • 請求的頭部 header
    • 請求的環境資訊
  • 響應
    • 狀態碼 status_code
    • 響應的資料
    • 響應的頭部

WSGI(Web Server Gateway Interface) 的任務就是把上面的資料在 http server 和 python 程式之間簡單友好地傳遞。它是一個標準,被定義在PEP 333。需要 http server 和 python 程式都要遵守一定的規範,實現這個標準的約定內容,才能正常工作。

wsgi

應用程式端

WSGI 規定每個 python 程式(Application)必須是一個可呼叫的物件(實現了__call__ 函式的方法或者類),接受兩個引數 environ(WSGI 的環境資訊) 和 start_response(開始響應請求的函式),並且返回 iterable。幾點說明:

  1. environstart_response 由 http server 提供並實現
  2. environ 變數是包含了環境資訊的字典
  3. Application 內部在返回前呼叫 start_response
  4. start_response也是一個 callable,接受兩個必須的引數,status(HTTP狀態)和 response_headers(響應訊息的頭)
  5. 可呼叫物件要返回一個值,這個值是可迭代的。

說了這麼多的概念,再來看看程式碼的實現:

伺服器程式端

上面已經說過,標準要能夠確切地實行,必須要求程式端和伺服器端共同遵守。上面提到, envrionstart_response 都是伺服器端提供的。下面就看看,伺服器端要履行的義務。

  • 準備 environ 引數
  • 定義 start_response 函式
  • 呼叫程式端的可呼叫物件

PEP 333 裡給出了一個 wsgi server 的簡單實現,我又簡化了一下——去除一些異常處理和判斷,新增了一點註釋:

中間層 middleware

有些程式可能處於伺服器端和程式端兩者之間:對於伺服器程式,它就是應用程式;而對於應用程式,它就是伺服器程式。這就是中間層 middleware。middleware 對伺服器程式和應用是透明的,它像一個代理/管道一樣,把接收到的請求進行一些處理,然後往後傳遞,一直傳遞到客戶端程式,最後把程式的客戶端處理的結果再返回。如下圖所示:

middleware 做了兩件事情:

  1. 被伺服器程式(有可能是其他 middleware)呼叫,返回結果回去
  2. 呼叫應用程式(有可能是其他 middleware),把引數傳遞過去

PEP 333 上面給出了 middleware 的可能使用場景:

  • 根據 url 把請求給到不同的客戶端程式(url routing)
  • 允許多個客戶端程式/web 框架同時執行,就是把接到的同一個請求傳遞給多個程式。
  • 負載均衡和遠端處理:把請求在網路上傳輸
  • 應答的過濾處理

那麼簡單地 middleware 實現是怎麼樣的呢?下面的程式碼實現的是一個簡單地 url routing 的 middleware:

怎麼在程式裡面使用呢?

注:上面的程式碼來自這篇部落格

瞭解更多?

對於普通的開發者來說,瞭解到上面的知識已經足夠,並不需要掌握每一個細節。

Only authors of web servers and programming frameworks need to know every detail and corner case of the WSGI design. You don’t need to understand every detail of WSGI just to install a WSGI application or to write a web application using an existing framework.

想要更多的話,就去看 PEP333,文件裡還有下面更多的知識:

  • 錯誤處理
  • environ 變數包含哪些值,都是什麼意思。
  • 輸入和輸出的細節
  • start_response 的更多規範
  • content-length 等頭部規範
  • 快取和文字流
  • unicode 和多語言處理
  • ……

參考資料

相關文章