【轉】常見的網關協議

 

常見的網關協議

在工做中一直使用PHP,但知道怎麼開車,不知道車是怎麼跑的是不行的,否則出問題了也不知道出在哪裏,所以瞭解下PHP-FPM的運行原理。、php

CGI

通用網絡接口(Common Gateway Interface),是用來規定Web Server和應用程序直接進行數據數據傳輸的協議。能夠用任意語言來實現,只要咱們使用的語言的可以支持標準輸入、標準輸出及環境變量等處理,就可以開發出一個CGI程序。html

 

CGI的運行過程:python

  1. 用戶訪問Web應用,發起一個HTTP請求,Web服務受到該請求;
  2. HTTP服務器將請求數據從HTTP請求中解析出來,根據請求的URL建立一個新的CGI進程,並經過環境變量和標準輸入傳入到CGI進程中;
  3. CGI進程根據請求進行邏輯處理,鏈接其餘服務請求數據或者從DB獲取數據或者只是單純的進行邏輯運算;
  4. CGI進程將處理的結果寫入到標準輸出中;
  5. Web服務器從標準輸出中讀取相應,並返回給用戶;
  6. Web服務器關閉CGI進程。

從上面能夠看出,對於每個用戶請求,都須要從新fork一個子進程處理請求、請求結束銷燬子進程的過程,若是是少許請求,若是是大併發,這種fork-and-execute顯然不適合,這是就出現了下面要講的fastcgi模式。web

FastCGI模式

快速通用網關接口(Fast Common Gateway Interface/FastCGI)是CGI的改進版,FastCGI的提出旨在減小Web服務器與CGI進程交互的開銷,使得服務器可以服務更多的請求。與CGI每次建立一個子進程不一樣的是,FastCGI的CGI進程在服務器啓動的時候就已經建立好了(常駐形式),並由FastCGI進程管理器管理,而不是由Web服務器建立。而且,與CGI經過標準輸入和標準輸出進行通訊不一樣的是,Web服務器和FastCGI進程之間是經過IPC(進程間通訊)來處理用戶的請求的服務器

FastCGI處理請求的過程:
  1. Web Server啓動時載入FastCGI進程管理器;
  2. FastCGI進程管理器進行自身初始化,並根據配置啓動多個CGI進程並循環等待來自Web Server的請求;
  3. 用戶訪問Web應用,發起一個HTTP請求,Web接受到請求後,將請求經過IPC通訊轉發一個CGI進程,Web Server將環境變量和請求數據寫入到標準輸出(流數據包),由CGI進程讀取。
  4. CGI進程完成處理後將結果輸出到標準輸出(流數據包),而後接續等待下一個請求;
  5. Web Server從標準輸出讀取請求結果並返回給用戶。
FastCGI通訊協議

同HTTP同樣,FastCGI由消息頭和消息體組成網絡


主要消息頭以下:併發

消息頭 做用
Version 協議版本號
Type 消息的類型,用於指定指定處理這個消息的方法
RequestID 標識當前所屬的FastCGI請求,若是一個鏈接僅處理一個請求,RequestID存在的意義就不大了
Content Length 數據包包體所佔字節數

消息類型定義:app

消息類型 描述
BEGIN_REUQEST 從Web Server發往CGI,表示開始處理新的請求,其中帶RequestID
ABORT_REQUEST 從Web Server發往CGI,表示終止一個處理中的請求
END_REQUESST CGI發送給Web Server,表示該請求完成,
返回數據裏包含返回代碼,決定請求是否成功處理
PARAMS 從Web Server發往CGI,能夠發送多個數據包,
發送接收標識爲一個長度爲0的空包,該中的數據類型和CGI協議一致
STDIN 從Web Server發往CGI,用於CGI從中讀取用戶提交的POST數據
STDOUT 從Web Server發往CGI,包含返回給用戶的數據
 

具體交互過程:框架

  1. Web Server接收用戶請求,而後將請求轉發給FastCGI進程;
  2. FastCgi進程決定是否處理請求,若是接收請求,則從鏈接中讀取數據;
  3. Web Server發送包含RequestIDBEGIN_REQUEST類型消息給CGI進程,後續全部的數據包都會帶上該RequestID,而後Web Server發送任一的PARAMS類型消息到FastCGI進程,發送接收後,Web服務器發送一個空的PARAMS消息包,表示PARAMS類型消息發送完畢,若是包含POST數據,Web Server會經過STDIN消息類型發送給FastCGI進程,當POST內容發送完畢後,會發送一個空的STDIN消息包;
  4. CGI進程從鏈接中讀取相關數據,若是拒絕請求則發送ENDQUEST請求,不然讀取請求數據,進行處理,將處理結果經過STDOUT消息類型發送給Web Server,並經過ENDREQUEST告知Web Server處理的結果。

PHP-FPM

PHP-FPM(PHP-FastCGI Process Manager),是PHP FastCGI的實現,提供了進程管理的功能。
PHP-FPM由兩種進程組成:Master進程和Worker進程,一個PHP-FPM一般只有一個Master進程,用來管理Worker進程,但其中一個子進程異常退出後,可以重啓新的子進程,還負責其餘管理功能,如平滑啓動等;一個PHP-FPM一般存在多個Worker進程,全部的Worker進程監聽同一個端口,當一個請求進來時,誰搶到就誰負責處理,每一個進程內嵌一個PHP解釋器,用來執行PHP代碼。函數

Nginx和PHP-FPM

經過指令fastcig_pass指定fastcgi監聽的地址(TCP/UDS),Nginx在接收相關請求時,會將請求經過改地址進行轉發。


WSGI

Web Server Gateway Interface,是用在python web框架編寫的Web Server和Web Application之間通訊的規範,要實現WSGI協議,必須同時實現Web Server和Web Application。

有了WSGI協議,只要server和application都遵循WSGI協議,那麼就能夠隨意的組合。好比,uWSGI和Gunicor是實現了WSGI協議的Server端,Django、Flask是實現了WSGI協議的Application端,那麼實際使用時,能夠隨意搭配使用。

實現簡單的WSGI服務
Web Application

一個可調用對象(可使方法/函數/類/對象,只要有obj.__call__便可)
接受2個參數:

  1. 字典environ,包含環境變量;
  2. 回調函數start_response(),用來發送HTTP相應(包括HTTP狀態碼、HTTP返回報頭)
    Applicatin層無需關心environstart_response()是如何實現的,只須要直接使用它們便可。
    返回:可迭代對象,內容是返回包的內容(字符串)
Web Server

Web Server的做用就是構建一個可讓Application成功執行的環境,從輸入獲取正確的請求並解析,傳遞給Application,而後返回正確的Response。

Server層無需關心application對象是如何運做的,只須要傳入什麼和會返回什麼便可。

Web Middle

除了ApplicationServerwsgi協議還規範了Midlle層,Middle介於ApplicationServer之間,Middle對於ApplicationServer來講是透明的,對於Application來講,Middle就是Server;對於Server來講,Middle就是Application。例如,服務器拿到了客戶端請求的URL, 根據目標URL,將請求消息路由到不一樣的應用對象。在Python中能夠實現爲裝飾器。以下,是一個簡單的實現:

 

常見的Python web框架都實現了wsgi server,但性能並非很好,經常僅適用於開發環境;在生產環境中,使用最廣的仍是GunicoruWSGI

與uWSGI/uwsgi的區別
  1. uwsgi: 一種線路協議而不是通訊協議,在此經常使用於在uWSGI服務器與其餘網絡服務器的數據通訊,其中Nginx有插件支持該協議
  2. uWSGI:一個web服務器,實現了WSGI協議、uwsgi協議、http協議等,對外可使用uwsgi進行通訊,對內使用WSGI協議調用具體的Application

Refer

  1. CGI 和 FastCGI 協議的運行原理
  2. 深刻理解 FastCGI 協議以及在 PHP 中的實現
  3. CGI、FastCGI和PHP-FPM關係圖解
  4. FastCGI 進程管理器(FPM
  5. 網關協議學習:CGI、FastCGI、WSGI
  6. WSGI初探
  7. Python Web開發最難懂的WSGI協議,到底包含哪些內容?
  8. Python拾遺 - WSGI規範
相關文章
相關標籤/搜索