php-fpm是一種master(主)/worker(子)多流程架構,與nginx設計風格有點類似。 master進程主要負責CGI及PHP環境初始化、事件監聽、子進程狀態等等,worker進程負責處理php請求。
在介紹運作原理之前,我們先了解下它的幾種運作模式。
運行模式
php-fpm支援三種運行模式,分別為static、ondemand、dynamic,預設為dynamic 。
static:靜態模式,啟動時分配固定的worker進程。
ondemand:按需分配,當收到使用者請求時fork worker進程。
dynamic:動態模式,啟動時分配固定的進程。伴隨著請求數增加,在設定的浮動範圍調整worker進程。
這三種模式各有千秋,大家可以依照不同的環境調整對應的配置。
以下進入本文主題,著重介紹php-fpm運行原理。
相關推薦:《PHP入門教學》
運行原理
php-fpm採用master/worker架構設計,前面簡單描述master和worker進程模組的功能。以下將詳細講解這兩個模組的運作原理。
master流程
master行程工作流程分成4個階段,如下圖:
1. cgi初始化階段:分別呼叫fcgi_init()和sapi_startup()函數,註冊進程訊號以及初始化sapi_globals全域變數。
2. php環境初始化階段:由cgi_sapi_module.startup 觸發。實際呼叫php_cgi_startup函數,而php_cgi_startup內部又呼叫php_module_startup執行。
php_module_startup主要功能:
a).載入和解析php配置;
b).載入php模組並記入函數符號表(function_table);
c).載入zend擴充;
d).設定停用函數與類別庫設定;
e).註冊回收記憶體方法;
3. php -fpm初始化階段:執行fpm_init()函數。負責解析php-fpm.conf檔案配置,取得進程相關參數(允許進程開啟的最大檔案數等),初始化進程池及事件模型等操作。
4. php-fpm運行階段:執行fpm_run() 函數,執行後主程序發生阻塞。此階段分為兩部分:fork子程序和循環事件。
fork子程序部分交由fpm_children_create_initial函式處理( 註:ondemand模式在fpm_pctl_on_socket_accept函式建立)。
循環事件部分透過fpm_event_loop函數處理,其內部是一個死循環,負責事件的收集工作。
worker進程
worker進程分為 接收客戶端請求、處理請求、請求結束三個階段。
1. 接收客戶端請求:執行fcgi_accept_request函數,其內部透過呼叫accept函數來取得客戶端請求。
//请求锁 FCGI_LOCK(req->listen_socket); req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); //释放锁 FCGI_UNLOCK(req->listen_socket);
從上面的程式碼,可以注意到accept之前有一個請求鎖的操作,這麼設計是為了避免請求出現「驚群」的現象。當然,這是一個可選的選項,可以取消該功能。
2. 處理請求階段:首先,分別呼叫fpm_request_info、php_request_startup取得請求內容及註冊全域變數($_GET、$_POST、$_SERVER、$_ENV、$_FILES);然後根據請求資訊呼叫php_fopen_primary_script存取腳本檔;最後交給php_execute_script執行。 php_execute_script內部呼叫zend_execute_scripts方法將腳本交給zend引擎處理。
3. 請求結束階段:執行php_request_shutdown函數。此時 回呼register_shutdown_function註冊的函數及__destruct()方法,發送回應內容、釋放記憶體等操作。
總結
php-fpm採用master/worker架構設計, master流程負責CGI、PHP公共環境的初始化及事件監聽作業。 worker進程負責請求的處理功能。在worker進程處理請求時,無需再次初始化PHP運行環境,這也是php-fpm效能優異的原因之一。
以上是php-fpm工作原理是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!