王帅:深入PHP内核(二)——SAPI探究(精辟)
SAPI是Server Application Programming Interface(服務(wù)器應(yīng)用編程接口)的縮寫(xiě)。PHP通過(guò)SAPI提供了一組接口,供應(yīng)用和PHP內(nèi)核之間進(jìn)行數(shù)據(jù)交互。
簡(jiǎn)單的講,就像函數(shù)的輸入和輸出一樣,我們通過(guò)Linux命令行執(zhí)行一段PHP代碼,本質(zhì)是Linux的Shell通過(guò)PHP的SAPI傳入一組參數(shù),Zend引擎執(zhí)行后,返回給shell,由shell顯示出來(lái)的過(guò)程。同樣的,通過(guò)Apache調(diào)用PHP,通過(guò)Web服務(wù)器給SAPI傳入數(shù)據(jù),Zend引擎執(zhí)行后,返回給Apache,由Apache顯示在頁(yè)面上。
圖1. PHP架構(gòu)圖
PHP提供很多種形式的接口,包括apache、apache2filter、apache2handler、caudium、cgi 、cgi-fcgi、cli、cli-server、continuity、embed、isapi、litespeed、milter、nsapi、phttpd pi3web、roxen、thttpd、tux和webjames。但是常用的只有5種形式,CLI/CGI(命令行)、Multiprocess(多進(jìn)程)、Multithreaded(多線程)、FastCGI和Embedded(內(nèi)嵌)。
PHP提供了一個(gè)函數(shù)查看當(dāng)前SAPI接口類型:
[php] view plaincopyPHP的運(yùn)行和加載
無(wú)論使用哪種SAPI,在PHP執(zhí)行腳本前后,都包含一系列事件:Module的Init(MINT)和Shutdown(MSHUTDOWN),Request 的Init(RINT)和Shutdown(RSHUTDOWN)。 第一階段是PHP模塊初始化階段(MINT),可以初始化擴(kuò)展內(nèi)部變量、分配資源和注冊(cè)資源處理器,在整個(gè)PHP實(shí)例生命周期內(nèi),該過(guò)程只執(zhí)行一次。
什么是PHP模塊?通過(guò)上面的PHP架構(gòu)圖,在PHP中可以使用get_loaded_extensions 函數(shù)來(lái)查看所有編譯并加載的模塊/擴(kuò)展,相當(dāng)于CLI模式下的php -m。
以PHP的Memcached擴(kuò)展源代碼為例:
[php] view plaincopy第三階段,請(qǐng)求處理完成后,會(huì)調(diào)用PHP_RSHUTDOWN_FUNCTION進(jìn)行回收,這是每個(gè)擴(kuò)展的請(qǐng)求關(guān)閉函數(shù),執(zhí)行最后的清理工作。Zend引擎執(zhí)行清理過(guò)程、垃圾收集、對(duì)之前的請(qǐng)求期間用到的每個(gè)變量執(zhí)行unset。請(qǐng)求完成可能是執(zhí)行到腳本完成,也可能是調(diào)用die()或exit()函數(shù)完成
第四階段,當(dāng)PHP生命周期結(jié)束時(shí)候,PHP_MSHUTDOWN_FUNCTION對(duì)模塊進(jìn)行回收處理,這是每個(gè)擴(kuò)展的模塊關(guān)閉函數(shù),用于關(guān)閉自己的內(nèi)核子系統(tǒng)。
[php] view plaincopy常見(jiàn)的運(yùn)行模式
常見(jiàn)的SAPI模式有五種:
- CLI和CGI模式(單進(jìn)程模式)
- 多進(jìn)程模式
- 多線程模式
- FastCGI模式
- 嵌入式
1. CLI/CGI模式
CLI和CGI都屬于單進(jìn)程模式,PHP的生命周期在一次請(qǐng)求中完成。也就是說(shuō)每次執(zhí)行PHP腳本,都會(huì)執(zhí)行第二部分講的四個(gè)INT和Shutdown事件。
圖2. CGI/CLI生命周期
2. 多進(jìn)程模式(Multiprocess)
多進(jìn)程模式可以將PHP內(nèi)置到Web Server中,PHP可以編譯成Apache下的prefork MPM模式和APXS模塊,當(dāng)Apache啟動(dòng)后,會(huì)fork很多子進(jìn)程,每個(gè)子進(jìn)程擁有自己獨(dú)立的進(jìn)程地址空間。
圖3. 多進(jìn)程模式生命周期
在一個(gè)子進(jìn)程中,PHP的生命周期是調(diào)用MINT啟動(dòng)后,執(zhí)行多次請(qǐng)求(RINT/RSHUTDOWN),在Apache關(guān)閉或進(jìn)程結(jié)束后,才會(huì)調(diào)用MSHUTDOWN進(jìn)行回收階段。
圖4. 多進(jìn)程的生命周期
多進(jìn)程模型中,每個(gè)子進(jìn)程都是獨(dú)立運(yùn)行,沒(méi)有代碼和數(shù)據(jù)共享,因此一個(gè)子進(jìn)程終止退出和重新生成,不會(huì)影響其他子進(jìn)程的穩(wěn)定。
3. 多線程模式(Multithreaded)
Apache2的Worker MPM采用了多線程模型,在一個(gè)進(jìn)程下創(chuàng)建多個(gè)線程,在同一個(gè)進(jìn)程地址空間執(zhí)行。
圖5. 多線程生命周期
4. FastCGI模式
在我們用的Nginx+PHP-FPM用的就是FastCGI模式,Fastcgi是一種特殊的CGI模式,是一種常駐進(jìn)程類型的CGI,運(yùn)行后可以Fork多個(gè)進(jìn)程,不用花費(fèi)時(shí)間動(dòng)態(tài)的Fork子進(jìn)程,也不需要每次請(qǐng)求都調(diào)用MINT/MSHUTDOWN。PHP通過(guò)PHP-FPM來(lái)管理和調(diào)度FastCGI的進(jìn)程池。Nginx和PHP-FPM通過(guò)本地的TCP Socket和Unix Socket 進(jìn)行通信。
圖6. FastCGI模式生命周期
PHP-FPM進(jìn)程管理器自身初始化,啟動(dòng)多個(gè)CGI解釋器進(jìn)程等待來(lái)自Nginx的請(qǐng)求。當(dāng)客戶端請(qǐng)求達(dá)到PHP-FPM,管理器選擇到一個(gè)CGI進(jìn)程進(jìn)行處理,Nginx將CGI環(huán)境變量和標(biāo)準(zhǔn)輸入發(fā)送到一個(gè)PHP-CIG子進(jìn)程。PHP-CGI子進(jìn)程處理完成后,將標(biāo)準(zhǔn)輸出和錯(cuò)誤信息返回給Nginx,當(dāng)PHP-CGI子進(jìn)程關(guān)閉連接時(shí),請(qǐng)求處理完成。PHP-CGI子進(jìn)程等待著下一個(gè)連接。
可以想象CGI的系統(tǒng)開(kāi)銷有多大。每一個(gè)Web 請(qǐng)求PHP都必須重新解析php.ini、載入全部擴(kuò)展并始化全部數(shù)據(jù)結(jié)構(gòu)。使用FastCGI,所有這些都只在進(jìn)程啟動(dòng)時(shí)發(fā)生一次。另外,對(duì)于數(shù)據(jù)庫(kù)和Memcache的持續(xù)連接可以工作。
5. 內(nèi)嵌模式(Embedded)
Embed SAPI是一種特殊的SAPI,允許在C/C++語(yǔ)言中調(diào)用PHP提供的函數(shù)。這種SAPI和CLI模式一樣,按照Module Init => Request Init => Request => Request Shutdown => Module Shutdown的模式運(yùn)行。
Embed SAPI可以調(diào)用PHP豐富的類庫(kù),也可以實(shí)現(xiàn)高級(jí)玩法,比如可以查看PHP的OPCODE(PHP執(zhí)行的中間碼,Zend引擎的指令,由PHP代碼生成)。
詳細(xì)請(qǐng)見(jiàn): http://www.laruence.com/2008/09/23/539.html
SAPI的運(yùn)行機(jī)制
我們以CGI為例,看一下SAPI的運(yùn)行機(jī)制。
[php] view plaincopy由上面代碼可見(jiàn),PHP的SAPI像是面向?qū)ο笾谢?#xff0c;SAPI.h和SAPI.c包含的函數(shù)是抽象基類的聲明和定義,各個(gè)服務(wù)器用的SAPI模式,則是繼承了這個(gè)基類,并重新定義基類方法的子類。
總結(jié)
PHP的SAPI是Zend引擎提供的一組標(biāo)準(zhǔn)交互接口,通過(guò)注冊(cè)初始化、析構(gòu)、輸入、輸出等接口,我們可以將應(yīng)用程序運(yùn)行在Zend引擎上,也可以把PHP嵌入到類似Apache的Web Server中。PHP常見(jiàn)的SAPI模式有五種,CGI/CLI模式、多進(jìn)程模式、多線程模式、FastCGI模式和內(nèi)嵌模式。
了解PHP的SAPI機(jī)制意義重大,幫助我們理解PHP的生命周期,并了解如何更好的通過(guò)C/C++為PHP編寫(xiě)擴(kuò)展,并在生命周期中找到提高系統(tǒng)性能的方式。
關(guān)于作者:王帥,騰訊企業(yè)QQ SaaS團(tuán)隊(duì)Leader。來(lái)源:http://www.csdn.net/article/2014-09-26/2821885-exploring-of-the-php-2
總結(jié)
以上是生活随笔為你收集整理的王帅:深入PHP内核(二)——SAPI探究(精辟)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 交行是什么银行
- 下一篇: 小规模季度45万免税会计分录