詳解 nginx php-fpm 工作機制

周焱發表於2018-11-05

圖解

詳解 nginx php-fpm 工作機制

Nginx

nginx是目前較流行的web server

CGI

原先web server只能處理html等靜態資源,後來出現了CGI協議,通過這個協議,開發者可以使用任何語言處理web server發來的請求,如php python nodejs等,理論上支援cgi的語言程式都可以,qzone早期的服務端版本就是c開發的cgi程式。

FastCGI

FastCGI,顧名思義為更快的 CGI,由於CGI每處理一個請求都要fork一個程式,隨著網際網路的發展,這種低效的方式已經不能滿足需求,於是一個程式可處理多個請求的FastCGI就誕生了.

Php-fpm

php-fpm是 FastCGI 的實現,並提供了程式管理的功能,包含master 和 worker 兩種程式。

  • master 建立並監聽socket,fork多個woker程式,通過共享記憶體獲取worker的狀態,進而通過訊號控制worker程式
  • worker 自由accept cgi請求,
  • master通過共享記憶體獲取worker程式的資訊,比如worker程式當前狀態、已處理請求數等,當master程式要殺掉一個worker程式時則通過傳送訊號的方式通知worker程式。

網上很多php-fpm的文章都說master監聽埠,然後再分配給worker處理,這個是不正確的,fpm的master程式與worker程式之間不會直接進行通訊,worker 自由accept cgi請求。

fpm其實可以同時監聽多個埠,每個埠對應一個worker pool,而每個pool下對應多個worker程式,這樣不同業務可以用不同的woker pool處理。

再看看php原始碼中是如何處理cgi請求的

  1. 等待請求: worker程式阻塞在fcgi_accept_request()等待請求
  2. 解析請求: fastcgi請求到達後被worker接收,然後開始接收並解析請求資料,直到request資料完全到
  3. 請求初始化: 執行php_request_startup(),此階段會呼叫每個擴充套件的:PHP_RINIT_FUNCTION()
  4. 編譯、執行: 由php_execute_script()完成PHP指令碼的編譯、執行(這一步就是我們執行我們寫的php程式碼了)
  5. 關閉請求: 請求完成後執行php_request_shutdown(),此階段會呼叫每個擴充套件的:PHP_RSHUTDOWN_FUNCTION(),然後進入步驟1

fpm程式管理

fpm程式管理有3種方式

  1. static: 在啟動時master按照pm.max_children配置fork出相應數量的worker程式,即保持worker程式數不變
  2. dynamic: 動態程式管理,在fpm啟動時按照pm.start_servers初始化一定數量的worker,執行期間如果master發現空閒worker數低於pm.min_spare_servers配置數(請求比較多,worker處理不過來了)則會fork worker程式,但總的worker數不能超過pm.max_children,如果master發現空閒worker數超過了pm.max_spare_servers(閒著的worker太多了)則會殺掉一些worker,避免佔用過多資源,master通過這4個值來控制worker數
  3. ondemand: 這種方式一般很少用,在啟動時不分配worker程式,等到有請求了後再通知master程式fork worker程式,總的worker數不超過pm.max_children,處理完成後worker程式不會立即退出,當空閒時間超過pm.process_idle_timeout後再退出

fpm 超時設定

在php-fpm.conf中有一個request_terminate_timeout的配置,如果worker處理一個請求的總時長超過了這個值,那麼master將會向此worker程式傳送kill -TERM訊號殺掉worker程式,預設值為0表示關閉此機制,另外fpm中slow log也是在這裡完成的。

常見問題

502

1.php-fpm.conf中request_terminate_timeout,如果超過這個時間,指令碼停止執行,worker程式也會退出,這是nginx就會返回502,,可以優化worker處理速度解決 2. 沒有空閒的worker去接受cgi請求,也會返回502,這時可以通過調整worker數量來解決

504

nginx 超時時間小於php超時時間導致

https://github.com/pangudashu/php7-internal/blob/master/1/fpm.md

相關文章