深入瞭解SAPI
一、SAPI比較
1. SAPI
伺服器應用程式程式設計介面,就是伺服器與程式語言之間互動的介面。比如Linux命令列執行一段PHP程式碼,其實是Linux shell通過PHP SAPI傳入一組引數,zend引擎執行後返回給shell。在PHP生命週期的各個階段,一些與服務相關的操作都是通過SAPI介面實現。
php_sapi_name()可以檢視當前SAPI介面的型別。 如 cli(php -r "echo php_sapi_name();")、fpm-fcgi等
2. PHP執行和載入的4個階段
①Minit 模組初始化階段,可以初始化php擴充套件、類庫的內部變數、註冊常量,定義模組使用的類等。
②Rinit 請求初始化階段,在模組初始化並激活後,會建立PHP執行環境,初始化本次請求所需的環境變數,比如 $_SERVER,$_SESSION
。
③Rshutdown 請求關閉階段,執行最後的清理工作,釋放所有處理本次請求的資源(申請的變數)。請求完成可能是執行到指令碼完成,也可能是呼叫die()或exit()函式完成
④Mshutdown 模組回收階段,用於關閉自己的核心子系統,釋放沒存。
3. SAPI 5種執行模式
①單程序模式(CLI,CGI),每次執行PHP指令碼,都會執行第二部分講的四個INT和Shutdown事件。當用戶請求數量非常多時,會大量擠佔系統的資源如記憶體,CPU時間等,造成系統開銷很大
②多程序模式(Apache下的prefork MPM模式),會fork很多子程序,每個子程序擁有自己獨立的程序地址空間,在一個子程序中,PHP的生命週期是呼叫MINT啟動後,執行多次請求(RINT/RSHUTDOWN),在Apache關閉或程序結束後,才會呼叫MSHUTDOWN進行回收階段。
多程序模型中,每個子程序都是獨立執行,沒有程式碼和資料共享,因此一個子程序終止退出和重新生成,不會影響其他子程序的穩定。
③多執行緒模式(Apache2的Worker MPM),在一個程序下建立多個執行緒,在同一個程序地址空間執行
④fastCGI模式,nginx+php-fpm就是這個模式,fast-cgi是CGI的升級版本,FastCGI可以看成是一個常駐型的CGI,它可以一直執行著,執行後可以fork多個程序,不用花費時間動態Fork子程序。也不需要每次請求都呼叫MINT/MSHUTDOWN。
⑤內嵌模式,允許在C/C++語言中呼叫PHP提供的函式,執行模式和CGI一樣,執行4個階段
二、php-fpm執行原理
- CGI:是個協議,伺服器發起請求,傳給PHP解析器,傳遞哪些資料,以什麼格式,由CGI決定
- fastcgi:是個協議,提高CGI效能的,不用每次都去初始化,程序不夠用,會預先啟動幾個程序,程序空閒太多了也會停掉一些,fastCGI對程序的管理,提高效能,節約了資源
- php-fpm:實現fastCGI協議的程式,被PHP官方收了,也提供了程序管理功能,程序包含 master 程序和 worker 程序兩種程序。 master 程序只有一個,負責監聽埠分發請求,接收來自 Web Server 的請求,而 worker 程序則一般有多個(具體數量根據實際需要配置),每個程序內部都嵌入了一個 PHP 直譯器,是 PHP 程式碼真正執行的地方。
- php-cgi:cgi直譯器程序
FastCGI的工作原理:
- Web Server啟動時載入FastCGI程序管理器
- FastCGI程序管理器自身初始化,啟動多個CGI直譯器(可見多個php-cgi)並等待來自Web Server的連線
- 當客戶端請求到達Web Server時,FastCGI程序管理器選擇並連線到一個CGI直譯器。Web Server將CGI環境變數和標準輸入傳送到FastCGI子程序php-cgi
- FastCGI子程序完成處理後將標準輸出和錯誤資訊從同一連線返回Web Server。當FastCGI子程序關閉連線時,請求便告知處理完成。FastCGI子程序接著等待並處理來自FastCGI繼承管理器的下一個連線
使用FastCGI,系統開銷小。另外,對於資料庫和Memcache的持續連線可以工作。
資料庫短連線connect:請求關閉階段,釋放請求所用的資源,資料庫連線控制代碼也會被釋放
資料庫長連線pconnect:請求關閉後,PHP會收留此次連線,即使主動關閉也不會關閉而是收留,下次有開啟相同連線的請求時,PHP直接把收留的控制代碼拿出來,省去建立連線的過程。
php-fpm實現長連線也需要配合資料庫一些配置,一個程序收留一個連線,資料庫連線的數量就是子程序數量,所以資料庫允許連線數就要大於子程序數。
三、php-fpm程序管理的三種模式
php-fpm支援三種執行模式,分別為static、ondemand、dynamic,預設為dynamic 。
- static : 靜態模式,啟動時分配固定的worker程序。只需要考慮max_children的數量,數量取決於cpu的個數和應用的響應時間。
- ondemand: 按需分配,啟動時不分配任何程序,當收到使用者請求時才啟動程序。 master程序檢查work程序的數量是否受限,是否有空閒的work程序,沒有就新建work程序。在大流量的系統上master程序會變得繁忙,佔用系統cpu資源,不適合大流量環境的部署。
- dynamic: 動態模式,啟動時分配固定的程序。伴隨著請求數增加,在設定的浮動範圍調整worker程序。
pm = dynamic//動態程序管理,對於專用伺服器,可以設定為static,靜態一次性啟動最大子程序數,不會變化。 pm.max_children = 50 //最大子程序數,ps aux可以檢視 pm.start_servers = 20 //啟動服務時會啟動的程序數 pm.min_spare_servers = 5 //保證空閒子程序數的最小值,如果空閒程序小於這個值,php-fpm服務會建立新的子程序。 pm.max_spare_servers = 35 //保證空閒子程序數的最大值,如果空閒程序高於這個值,就進行清理。 pm.max_requests = 500//定義一個子程序最多處理的請求數,達到這個值,程序自動退出。目的是為了控制記憶體溢位,使記憶體在一個可控範圍內。但是如果設定的很小,有可能多個程序同時達到這個值,同時重啟,就會導致PHP停止響應直到重啟完畢。設定為0表示一直接受請求。
四、php-fpm慢日誌
如果一個php網站可以訪問,就是訪問速度變慢了,可以通過php-fpm的慢執行日誌,清晰的瞭解到php的指令碼哪裡執行時間長,它可以定位到具體的程式碼行
vim /usr/local/php/etc/php-fpm.d/www.conf request_slowlog_timeout = 1 //超時時間 slowlog = /usr/local/php/var/log/www-slow.log 重啟php-fpm /etc/init.d/php-fpm reload
我在php檔案中加了一行 sleep(3);
,執行之後返回結果
參考文獻
1、 https://www.jianshu.com/p/c9a... php-fpm程序管理的三種模式
2、 https://www.jb51.net/article/... SAPI的5種執行模式
3、 http://blog.51cto.com/1260661... php-fpm慢日誌
4、 https://www.cnblogs.com/wpjam... php-fpm與mysql長連線