Nginx+FPM結構模型剖析及優化

Nginx+FPM結構模型剖析及優化

隨著php腳本語言使用的普及,目前webserice服務大部分都在用nginx+(php-fpm)的結構,了解了其工作過程后才可以在各個方面想辦法做調整優化和故障排查,從以下幾點總結一下這種模型。

一、nginx和php-fpm的關系和分工

nginx是web服務器,php-fpm是一個PHPFastCGI進程管理器,兩者遵循fastcgi的協議進行通信,nginx負責靜態類似html文件的處理,php-fpm負責php腳本語言的執行,這么設計的目的是為了解耦前端nginx和后端的php,不至于讓容易出問題的php腳本堵塞整個nginx的業務處理,影響用戶體驗,因為php腳本語言的執行是會比較容易出問題的。nginx之所以能處理成千上萬高并發業務,除其本身的異步非阻塞模式,在與和其他模塊的耦合擴展方法也是分不開的,在nginx的設計里不能接受的就是阻塞,不過并非完全沒有梗,比如說用到的最多的多進程單線程的模式,由于nginx日志沒有單獨的處理進程,如果收集日志時處理不當就會把worker進程堵死。

對應nginx+php-fpm的模型結構圖如下:

1、nginx的工作簡介

接到php的腳本請求后,nginx通過fastcgi_pass指令將請求傳遞給后端php-fpm的worker進程處理,在此過程中,nginx做了各種超時機制、緩存機制、buffer機制和長連接機制等來保障與后端的php-fpm能夠良性高效的合作。

在超時機制方面控制nginx對后端php的等待時間,通過各種timeout指令進行控制,例如:

fastcgi_connect_timeout : ?后端鏈接時間

fastcgi_send_timeout ?: ?數據發送時間,兩次成功發送時間差,不是整個發送時間

fastcgi_read_timeout ?: ?數據接收時間,兩次成功接收時間差,不是整個接收時間

當超時后會返回504超時的狀態碼,在buffer機制指令也有很多,例如:

fastcgi_buffer_size 存放fastcgi傳過來的響應頭,一般設置為分頁大小

fastcgi_buffers 存放fastcgi傳過來的相應內容,一般設置分頁的倍數,格式例如 8 ?4k|8k

另外還有一些其它的緩存、長連接機制不做介紹,當設置不合理時也會出現5XX錯誤,nginx的文章介紹寫了有很多的,不再做過多的說明。

2、php-fpm工作介紹

Php-fpm是一個PHPfastcgi進程管理器,在啟動后會有master和worker兩種進程,master負責接收外部信號和管理worker進程,worker進程是負責干活的,處理nginx傳過來的任務。

master進程只有一個,負責監聽端口和管理worker進程,每次傳來任務,與前端的nginx建立3次握手后放入連接隊列,供worker進程進行accept,當worker進程出現錯誤或執行超時時,負責將worker進程重啟或者殺掉,是php-fpm模型中的大內總管。

Worker進程是工作進程,每個worker進程都獨立的執行php程序腳本,然后把執行的結果通過fastcgi協議交給nginx,執行過程中受master的管理。在工作中,worker進程去競爭accept管理進程master的鏈接隊列,accept函數將從連接請求隊列中獲得連接信息,創建新的socket,并返回該套接字的fd,新創建的socket用于服務器與nginx的通信,而原來的套接字仍然處于監聽狀態。

php-fpm可以配置多個pool,所有pool由master統一管理監聽不同端口并分配不同worker進程池,worker進程池支持動態prefork同時也支持靜態開啟,服務器內存較大時建議直接計算后配置靜態資源池,可以減少頻繁prefork進程所帶來的開銷,提高服務質量,由于進程模型越跑程序耗費越大,因為每個worker進程可以配置執行多少個請求后進行重啟,對應的池子的指令和執行多少個請求的指令如下:

pm = static | dynamic | ondemand :靜態池、服務優先、內存優先

pm.max_children = 256 ?: 開啟的最大php進程數

pm.max_requests = 1024 ?: 在執行了1024個請求后重啟worker進程

這也是我們線上服務器的配置,我們線上用的web服務的機器是12核cpu、16G內存,nginx開啟12個worker進程,php開啟256個進程,跑起來后每個進程大概占用30M內存,也就是(256+12)*30=8G ,另外還跑了一些配管、監控、統計、日志收集等七七八八的軟件,整體業務是比較輕松的,這種靜態池的配置大大減少了prefork進程帶來的開銷,RT時間100ms以內的占到90%以上(這個與程序寫的如何有關),運行一段時間后的開銷截圖如下:

二、此模型結構常見的5XX

服務器端錯誤及優化

1、nginx日志里產生502錯誤

第一種情況,php-fpm的worker進程執行php程序腳本時,超過了配置的最長執行時間,master進程將worker進程殺掉,直接返回502。返回502后nginx對應的error日志是104: Connection reset by peer,對應的php執行時間的配置如下,一些版本中php-fpm的配置會覆蓋php.ini的配置,使php.ini的配置不起作用:

php.ini中默認30s:max_execution_time =

php-fpm中:request_terminate_timeout =

第二種情況,連接請求數(accpet之前)超出了端口所能監聽的tcp連接的最大值(backlog的值),進不了fpm等待accept的鏈接隊列,直接返回502,這里可能會產生tcp重傳;返回502后nginx對應的error日志是111: Connection refused, backlog的值是半連接和全連接的總和,他的存在也有短時間緩沖解耦nginx請求與fpm處理的作用,半連接指收到了syn請求,3次握手尚未建立,全連接指的是3次握手已經成功,不過尚未被accpet的請求,fpm里面有調節的參數,如果fpm的參數設置為-1,則默認走的是系統內核參數net.core.somaxconn的設置值,如果不設置可以在/proc/sys/net/core/somaxconn里查看,默認值是128,所以在連接請求較高的業務里要增大這個值。

第三種情況,網絡卡時,客戶端斷開連接,nginx處顯示499,然后php檢查到前端nginx產生abort后,又master結束此條任務的繼而產生502,一般此種情況的報警,先是499,過會兒變成502,再過一會變成504.

減少避免502報錯優化建議

502主要從php-fpm的配置方考慮,根據服務器情況,適量增大php-fpm的工作進程數,適當增加php的執行時間,適當增加backlog值。

php的工作進程數也不是越大越好,這種進程模型運行時間長了占的內存會增大,一般一個php進程是占到30M左右的內存,開多少合適自己算吧,nginx的worker進程一般也能跑到30M的內存,綜合計算一下;php的執行時間可以根據你的服務標準來設定,超過服務時間瀏覽器返回的是502錯誤,這個按照實際的情況處理吧,反正我是覺得執行的慢有返回結果總比直接返回502錯誤的強;至于backlog值,當程序寫的比較好時,建議設置其數量為php工作進程的1到2倍。

2、nginx日志里產生504錯誤

第一種情況,php的worker進程池處理慢,無法盡快處理等待accept的鏈接隊列,導致3次握手后的鏈接隊列長時間沒有被accept,nginx鏈接等待超時;返回504后nginx對應的error日志是110: Connection timed out

第二種情況,后端php-fpm執行腳本的時間太長,超過了nginx配置的超時機制,這個時候也是會報出504錯誤的。

第三種情況,客戶端的網絡及其差,php將請求處理完交給nginx后,nginx沒能在超時時間內將內容全部吐給用戶,這時也會超時,只有504而沒有502。

減少避免504報錯的優化建議

504主要從nginx的配置方考慮,根據業務情況配置好超時的各種機制,包含但不限于下屬參數:

fastcgi_connect_timeout

fastcgi_send_timeout

fastcgi_read_timeout

另外:在配置過程中,比如遇到大并發或者是特殊業務的場景,不合理的fd、buffer等設置也會帶來5XX錯誤,比如說大并發連接的業務要增大系統和單個程序的fd數量,如果是上傳業務要增大頭buffer等,這些要視情況而做優化,正所謂道法自然,術變萬千,要以不變應萬變。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容

  • Nginx簡介 解決基于進程模型產生的C10K問題,請求時即使無狀態連接如web服務都無法達到并發響應量級一萬的現...
    魏鎮坪閱讀 2,029評論 0 9
  • Nginx的工作原理 1.Nginx的模塊與工作原理 Nginx由內核和模塊組成,其中,內核的設計非常微小和簡潔,...
    架構飛毛腿閱讀 6,062評論 1 27
  • 《老男孩Linux運維》筆記 隱藏Nginx軟件版本號 一般來說,軟件的漏洞都和版本有關。因此要盡量隱藏對訪問用戶...
    Zhang21閱讀 3,669評論 0 28
  • 在實際的開發和應用中偶發的502,504讓人頭痛,下面轉發一個寫的比較全面的。 PHP-fpm PHP-FPM是一...
    daos閱讀 2,378評論 2 18
  • 01 孤獨≠矯情 我不想歌頌孤獨,也不想抱怨孤獨,更不想打著孤獨的名義無處呻吟矯情作祟。眾所周知,孤獨仿佛是個被文...
    丑妹閱讀 17,505評論 104 270