深刻理解PHP-FPM

FPM是什麼


FPM(FastCGI Process Manager)是PHP FASTCGI運行模式的一個進程管理器。php

問題來了,既然是進程管理器,用來管理什麼進程呢?
這就引出FastCGI協議web

什麼是FastCGI協議?
FastCGI是web服務器(如Nginx、Apache)和處理程序之間的一種通訊協議。它是與HTTP相似的一種應用層通訊協議。注意:它只是一種協議。
在網絡應用場景下,PHP並無像GOlang那樣實現HTTP網絡庫,而是實現的FastCGI協議,而後與web服務器配合實現了HTTP的處理,web服務器來處理HTTP請求,而後將解析的結果再經過FastCGI協議轉發給處理程序,處理程序處理完成後將結果返回給web服務器,web服務器再返回給用戶。安全

擴展之-經常使用的網絡處理模型服務器

  • 多進程模型:由一個主進程和多個子進程組成,主進程負責管理子進程,基本的網絡事件由多個子進程處理,Nginx採用的就是這種模型。
  • 多線程模型:與多進程類型,只是它是線程粒度,這種模型一般會由主進程監聽、接收請求,而後交由子線程處理,memcached就是這種模式;有的也是採用多進程那種模式-主線程只負責管理子線程不處理網絡事件,各個子線程監聽、接收、處理請求,memcached使用UDP協議時採用的是這種模式。

進程擁有獨立的地址空間及資源,而線程沒有,線程之間共享進程的地址空間及資源,因此在資源管理上多進程模型比較簡單,而多線程模型則須要考慮不一樣線程之間資源衝突,也就是線程安全。網絡

基本實現


FPM是一個多進程模型,它由一個master進程和多個worker進程組成。master進程啓動時會建立一個socket,可是不會接收、處理請求,而是fork出多個worker子進程完請求的接收及處理。多線程

master進程的主要工做是管理worker進程,負責fork或者kill掉進程,好比當請求比較多處理不過來時,master進程會嘗試fork新的worker進程進程處理,而當空閒worker進程比較多時則會殺掉部分子進程,避免佔用、浪費系統資源。併發

worker進程的主要工做是處理請求,每一個worker進程會競爭的Accept請求,接受成功後解析FastCGI,而後執行相應的腳本,處理完成後關閉請求,繼續等待新的鏈接,這就是一個worker進程的生命週期。從worker進程的生命週期能夠看到:一個worker進程只能處理一個請求,只有將一個請求處理完成後纔會處理下一個請求。這與Nginx的事件模型有很大的區別,Nginx的子進程經過epoll管理套接字,若是一個請求數據還未發送完成則會處理下一個請求,它是非阻塞的模型,只處理活躍的套接字。FPM的這種處理模式大大簡化了PHP的資源管理,使得在FPM模式下不須要考慮併發致使的資源衝突。socket

master進程與worker進程之間不會直接進行通訊,master通訊共享內存獲取worker進程的信息,好比worker進程當前狀態、已處理請求數等,master進程經過發送信號的方式殺掉worker進程。tcp

FPM能夠同時監聽多個端口,每一個端口對應一個worker pool,每一個pool下對應多個worker進程,相似Nginx中server的概念,這些歸屬不一樣pool的worker進程扔由一個master管理。worker pool的結構爲fpm_worker_pool_s,pool之間構成一個鏈表
在php-fpm.conf中經過[pool name]聲明一個worker pool,每一個pool各自配置監聽的地址、進程管理方式、worker進程數等。memcached

[pool name1]
listen = 127.0.0.1:9000
...
[pool name2]
listen = 127.0.0.1:9001
...
;isten = /dev/shm/php-fpm0.socket //可使用tcp或者unix socket的方式,可是必須區別於其餘池的配置,好比tcp的端口不能同樣,socket的文件不能同樣
pm=dynamic   //進程模型: static、dynamic、ondemand
pm.max_children=50 //最大worker進程數
pm.start_servers=5 //啓動時初始化的worker數
pm.min_spare_servers=5 //最小空閒worker數
pm.max_spare_servers=35  //最大空閒worker數
pm.process_idle_timeout=10  //worker空閒時間
pm.pm_max_requests //worker處理的最多請求數,超過這個值worker將被kill

擴展之PHP-FPM的多個進程池

每一個池使用不一樣的配置,各個池之間互不干涉。默認狀況下,PHP 只啓用了一個池,全部請求均在這個池中執行。一旦某些請求出現擁堵之類的狀況,那麼極可能會連累整個池出現問題;若是啓用多個池,那麼能夠把請求分門別類放到不一樣的池中執行,此時若是某些請求出現擁堵之類的狀況,那麼只會影響本身所在的池,從而控制故障的波及範圍。

設置多個進程池,每一個進程池分配不一樣的站點,能夠作到一個站佔用資源過多致使其它站也不能訪問的尷尬狀況。這使得網站能夠更好的運行,若是某個站點受到少許CC攻擊,也不至於拖跨全部的站點。

參考書籍:《PHP7內核剖析》

相關文章
相關標籤/搜索