在工做中一直使用PHP,但知道怎麼開車,不知道車是怎麼跑的是不行的,否則出問題了也不知道出在哪裏,所以瞭解下PHP-FPM的運行原理。、php
通用網絡接口(Common Gateway Interface),是用來規定Web Server和應用程序直接進行數據數據傳輸的協議。能夠用任意語言來實現,只要咱們使用的語言的可以支持標準輸入、標準輸出及環境變量等處理,就可以開發出一個CGI程序。html
CGI的運行過程:python
從上面能夠看出,對於每個用戶請求,都須要從新fork一個子進程處理請求、請求結束銷燬子進程的過程,若是是少許請求,若是是大併發,這種fork-and-execute
顯然不適合,這是就出現了下面要講的fastcgi
模式。web
快速通用網關接口(Fast Common Gateway Interface/FastCGI)是CGI的改進版,FastCGI的提出旨在減小Web服務器與CGI進程交互的開銷,使得服務器可以服務更多的請求。與CGI每次建立一個子進程不一樣的是,FastCGI的CGI進程在服務器啓動的時候就已經建立好了(常駐形式),並由FastCGI進程管理器管理,而不是由Web服務器建立。而且,與CGI經過標準輸入和標準輸出進行通訊不一樣的是,Web服務器和FastCGI進程之間是經過IPC(進程間通訊)來處理用戶的請求的。服務器
同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,包含返回給用戶的數據 |
具體交互過程:框架
RequestID
的BEGIN_REQUEST
類型消息給CGI進程,後續全部的數據包都會帶上該RequestID
,而後Web Server發送任一的PARAMS
類型消息到FastCGI進程,發送接收後,Web服務器發送一個空的PARAMS消息包,表示PARAMS
類型消息發送完畢,若是包含POST數據,Web Server會經過STDIN
消息類型發送給FastCGI進程,當POST內容發送完畢後,會發送一個空的STDIN
消息包;ENDQUEST
請求,不然讀取請求數據,進行處理,將處理結果經過STDOUT
消息類型發送給Web Server,並經過ENDREQUEST
告知Web Server處理的結果。PHP-FPM(PHP-FastCGI Process Manager),是PHP FastCGI的實現,提供了進程管理的功能。
PHP-FPM由兩種進程組成:Master進程和Worker進程,一個PHP-FPM一般只有一個Master進程,用來管理Worker進程,但其中一個子進程異常退出後,可以重啓新的子進程,還負責其餘管理功能,如平滑啓動等;一個PHP-FPM一般存在多個Worker進程,全部的Worker進程監聽同一個端口,當一個請求進來時,誰搶到就誰負責處理,每一個進程內嵌一個PHP解釋器,用來執行PHP代碼。函數
經過指令fastcig_pass
指定fastcgi監聽的地址(TCP/UDS),Nginx在接收相關請求時,會將請求經過改地址進行轉發。
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端,那麼實際使用時,能夠隨意搭配使用。
一個可調用對象(可使方法/函數/類/對象,只要有obj.__call__
便可)
接受2個參數:
environ
,包含環境變量;start_response()
,用來發送HTTP相應(包括HTTP狀態碼、HTTP返回報頭)Applicatin
層無需關心environ
和start_response()
是如何實現的,只須要直接使用它們便可。Web Server的做用就是構建一個可讓Application成功執行的環境,從輸入獲取正確的請求並解析,傳遞給Application,而後返回正確的Response。
Server
層無需關心application
對象是如何運做的,只須要傳入什麼和會返回什麼便可。
除了Application
和Server
,wsgi
協議還規範了Midlle
層,Middle
介於Application
和Server
之間,Middle
對於Application
和Server
來講是透明的,對於Application
來講,Middle
就是Server
;對於Server
來講,Middle
就是Application
。例如,服務器拿到了客戶端請求的URL, 根據目標URL,將請求消息路由到不一樣的應用對象。在Python中能夠實現爲裝飾器。以下,是一個簡單的實現:
常見的Python web框架都實現了wsgi server
,但性能並非很好,經常僅適用於開發環境;在生產環境中,使用最廣的仍是Gunicor
和uWSGI
。
uwsgi
: 一種線路協議而不是通訊協議,在此經常使用於在uWSGI服務器與其餘網絡服務器的數據通訊,其中Nginx有插件支持該協議uWSGI
:一個web服務器,實現了WSGI協議、uwsgi協議、http協議等,對外可使用uwsgi
進行通訊,對內使用WSGI
協議調用具體的Application
。