成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

PHP內(nèi)核了解:生命周期及運(yùn)行模式

瀏覽:105日期:2022-09-11 17:31:54
PHP運(yùn)行模式

1)CGI(通用網(wǎng)關(guān)接口 / Common Gateway Interface)2)FastCGI(常駐型CGI / Long-Live CGI)3)CLI(命令行運(yùn)行 / Command Line Interface)4)Web模塊模式(Apache等Web服務(wù)器運(yùn)行的模式)5)ISAPI(Internet Server Application Program Interface)備注:在PHP5.3以后,PHP不再有ISAPI模式

CGI是個(gè)協(xié)議,跟進(jìn)程什么的沒(méi)關(guān)系。那fastcgi又是什么呢?Fastcgi是用來(lái)提高CGI程序性能的。

PHP中的CGI實(shí)現(xiàn)

PHP的CGI實(shí)現(xiàn)本質(zhì)是是以socket編程實(shí)現(xiàn)一個(gè)TCP或UDP協(xié)議的服務(wù)器,當(dāng)啟動(dòng)時(shí),創(chuàng)建TCP/UDP協(xié)議的服務(wù)器的socket監(jiān)聽(tīng), 并接收相關(guān)請(qǐng)求進(jìn)行處理。這只是請(qǐng)求的處理,在此基礎(chǔ)上添加模塊初始化,sapi初始化,模塊關(guān)閉,sapi關(guān)閉等就構(gòu)成了整個(gè)CGI的生命周期。

PHP內(nèi)核了解:生命周期及運(yùn)行模式

CGI

CGI全稱是“通用網(wǎng)關(guān)接口”(Common Gateway Interface), 它可以讓一個(gè)客戶端,從網(wǎng)頁(yè)瀏覽器向執(zhí)行在Web服務(wù)器上的程序請(qǐng)求數(shù)據(jù)。

CGI描述了客戶端和這個(gè)程序之間傳輸數(shù)據(jù)的一種標(biāo)準(zhǔn)。CGI的一個(gè)目的是要獨(dú)立于任何語(yǔ)言的,所以CGI可以用任何一種語(yǔ)言編寫(xiě),只要這種語(yǔ)言具有標(biāo)準(zhǔn)輸入、輸出和環(huán)境變量。如php,perl,tcl等

CGI已經(jīng)是比較老的模式了,這幾年都很少用了。

每有一個(gè)用戶請(qǐng)求,都會(huì)先要?jiǎng)?chuàng)建CGI的子進(jìn)程,然后處理請(qǐng)求,處理完后結(jié)束這個(gè)子進(jìn)程,這就是Fork-And-Execute模式。 當(dāng)用戶請(qǐng)求數(shù)量非常多時(shí),會(huì)大量擠占系統(tǒng)的資源如內(nèi)存,CPU時(shí)間等,造成效能低下。 所以用CGI方式的服務(wù)器有多少連接請(qǐng)求就會(huì)有多少CGI子進(jìn)程,子進(jìn)程反復(fù)加載是CGI性能低下的主要原因。

當(dāng)web server收到/index.php這個(gè)請(qǐng)求后,會(huì)啟動(dòng)對(duì)應(yīng)的CGI程序,這里就是PHP的解析器。接下來(lái)PHP解析器會(huì)解析php.ini文件,初始化執(zhí)行環(huán)境,然后處理請(qǐng)求,再以規(guī)定CGI規(guī)定的格式返回處理后的結(jié)果,退出進(jìn)程。web server再把結(jié)果返回給瀏覽器。

FastCGI

fast-cgi 是cgi的升級(jí)版本,F(xiàn)astCGI 像是一個(gè)常駐 (long-live) 型的 CGI,它可以一直執(zhí)行著,只要激活后,不會(huì)每次都要花費(fèi)時(shí)間去 fork 一次 (這是 CGI 最為人詬病的 fork-and-execute 模式)。

FastCGI工作原理Web Server啟動(dòng)時(shí)載入FastCGI進(jìn)程管理器【PHP的FastCGI進(jìn)程管理器是PHP-FPM(php-FastCGI Process Manager)】(IIS ISAPI或Apache Module) FastCGI進(jìn)程管理器自身初始化,啟動(dòng)多個(gè)CGI解釋器進(jìn)程 (可見(jiàn)多個(gè)php-cgi.exe或php-cig)并等待來(lái)自Web Server的連接; 當(dāng)客戶端請(qǐng)求到達(dá)Web Server時(shí),F(xiàn)astCGI進(jìn)程管理器選擇并連接到一個(gè)CGI解釋器。Web server將CGI環(huán)境變量和標(biāo)準(zhǔn)輸入發(fā)送到FastCGI子進(jìn)程php-cgi FastCGI子進(jìn)程完成處理后將標(biāo)準(zhǔn)輸出和錯(cuò)誤信息從同一連接返回Web Server。當(dāng)FastCGI子進(jìn)程關(guān)閉連接時(shí),請(qǐng)求便告處理完成。FastCGI子進(jìn)程接著等待并處理來(lái)自FastCGI進(jìn)程管理器(運(yùn)行在 WebServer中)的下一個(gè)連接。 在正常的CGI模式中,php-cgi.exe在此便退出了。在CGI模式中,你可以想象 CGI通常有多慢。每一個(gè)Web請(qǐng)求PHP都必須重新解析php.ini、重新載入全部dll擴(kuò)展并重初始化全部數(shù)據(jù)結(jié)構(gòu)。使用FastCGI,所有這些都只在進(jìn)程啟動(dòng)時(shí)發(fā)生一次。一個(gè)額外的好處是,持續(xù)數(shù)據(jù)庫(kù)連接(Persistent database connection)可以工作。

備注:PHP的FastCGI進(jìn)程管理器是PHP-FPM(PHP-FastCGI Process Manager)

優(yōu)點(diǎn)從穩(wěn)定性上看,F(xiàn)astCGI是以獨(dú)立的進(jìn)程池來(lái)運(yùn)行CGI,單獨(dú)一個(gè)進(jìn)程死掉,系統(tǒng)可以很輕易的丟棄,然后重新分配新的進(jìn)程來(lái)運(yùn)行邏輯; 從安全性上看,F(xiàn)astCGI支持分布式運(yùn)算。FastCGI和宿主的Server完全獨(dú)立,F(xiàn)astCGI怎么down也不會(huì)把Server搞垮; 從性能上看,F(xiàn)astCGI把動(dòng)態(tài)邏輯的處理從Server中分離出來(lái),大負(fù)荷的IO處理還是留給宿主Server,這樣宿主Server可以一心一意作IO,對(duì)于一個(gè)普通的動(dòng)態(tài)網(wǎng)頁(yè)來(lái)說(shuō), 邏輯處理可能只有一小部分,大量的是圖片等靜態(tài)。不足

因?yàn)槭嵌噙M(jìn)程,所以比CGI多線程消耗更多的服務(wù)器內(nèi)存,PHP-CGI解釋器每進(jìn)程消耗7至25兆內(nèi)存,將這個(gè)數(shù)字乘以50或100就是很大的內(nèi)存數(shù)。

Nginx 0.8.46+PHP 5.2.14(FastCGI)服務(wù)器在3萬(wàn)并發(fā)連接下,開(kāi)啟的10個(gè)Nginx進(jìn)程消耗150M內(nèi)存(15M*10=150M),開(kāi)啟的64個(gè)php-cgi進(jìn)程消耗1280M內(nèi)存(20M*64=1280M),加上系統(tǒng)自身消耗的內(nèi)存,總共消耗不到2GB內(nèi)存。如果服務(wù)器內(nèi)存較小,完全可以只開(kāi)啟25個(gè)php-cgi進(jìn)程,這樣php-cgi消耗的總內(nèi)存數(shù)才500M。

上面的數(shù)據(jù)摘自Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建勝過(guò)Apache十倍的Web服務(wù)器(第6版)

CLI

PHP-CLI是PHP Command Line Interface的簡(jiǎn)稱,就是PHP在命令行運(yùn)行的接口,區(qū)別于在Web服務(wù)器上運(yùn)行的PHP環(huán)境(PHP-CGI,ISAPI等)。也就是說(shuō),PHP不單可以寫(xiě)前臺(tái)網(wǎng)頁(yè),它還可以用來(lái)寫(xiě)后臺(tái)的程序。 PHP的CLI Shell腳本適用于所有的PHP優(yōu)勢(shì),使創(chuàng)建要么支持腳本或系統(tǒng)甚至與GUI應(yīng)用程序的服務(wù)端,在Windows和Linux下都是支持PHP-CLI模式的。

我們?cè)贚inux下經(jīng)常使用”php –m”查找PHP安裝了那些擴(kuò)展就是PHP命令行運(yùn)行模式;

PHP開(kāi)始和結(jié)束階段

PHP開(kāi)始執(zhí)行以后會(huì)經(jīng)過(guò)兩個(gè)主要的階段:處理請(qǐng)求之前的開(kāi)始階段和請(qǐng)求之后的結(jié)束階段。

開(kāi)始階段模塊初始化階段MINIT

在整個(gè)SAPI生命周期內(nèi)(例如Apache啟動(dòng)以后的整個(gè)生命周期內(nèi)或者命令行程序整個(gè)執(zhí)行過(guò)程中), 該過(guò)程只進(jìn)行一次。

啟動(dòng)Apache后,PHP解釋程序也隨之啟動(dòng);PHP調(diào)用各個(gè)擴(kuò)展(模塊)的MINIT方法,從而使這些擴(kuò)展切換到可用狀態(tài)。

PHP_MINIT_FUNCTION(myphpextension){ // 注冊(cè)常量或者類等初始化操作 return SUCCESS; }模塊激活階段RINIT

該過(guò)程發(fā)生在請(qǐng)求階段, 例如通過(guò)url請(qǐng)求某個(gè)頁(yè)面,則在每次請(qǐng)求之前都會(huì)進(jìn)行模塊激活(RINIT請(qǐng)求開(kāi)始)。請(qǐng)求到達(dá)之后,SAPI層將控制權(quán)交給PHP層,PHP初始化本次請(qǐng)求執(zhí)行腳本所需的環(huán)境變量

例如是Session模塊的RINIT,如果在php.ini中啟用了Session 模塊,那在調(diào)用該模塊的RINIT時(shí)就會(huì)初始化$_SESSION變量,并將相關(guān)內(nèi)容讀入; 然后PHP會(huì)調(diào)用所有模塊RINIT函數(shù),即“請(qǐng)求初始化”。在這個(gè)階段各個(gè)模塊也可以執(zhí)行一些相關(guān)的操作, 模塊的RINIT函數(shù)和MINIT函數(shù)類似 ,RINIT方法可以看作是一個(gè)準(zhǔn)備過(guò)程,在程序執(zhí)行之前就會(huì)自動(dòng)啟動(dòng)。

結(jié)束階段

請(qǐng)求處理完后就進(jìn)入了結(jié)束階段, 一般腳本執(zhí)行到末尾或者通過(guò)調(diào)用exit()或者die()函數(shù),PHP都將進(jìn)入結(jié)束階段. 和開(kāi)始階段對(duì)應(yīng),結(jié)束階段也分為兩個(gè)環(huán)節(jié),一個(gè)在請(qǐng)求結(jié)束后(RSHUWDOWN),一個(gè)在SAPI生命周期結(jié)束時(shí)(MSHUTDOWN).

請(qǐng)求結(jié)束后(RSHUWDOWN)

請(qǐng)求處理完后就進(jìn)入了結(jié)束階段,PHP就會(huì)啟動(dòng)清理程序。它會(huì)按順序調(diào)用各個(gè)模塊的RSHUTDOWN方法。RSHUTDOWN用以清除程序運(yùn)行時(shí)產(chǎn)生的符號(hào)表,也就是對(duì)每個(gè)變量調(diào)用unset函數(shù)。

SAPI生命周期結(jié)束時(shí)(MSHUTDOWN)

最后,所有的請(qǐng)求都已處理完畢SAPI也準(zhǔn)備關(guān)閉了PHP調(diào)用每個(gè)擴(kuò)展的MSHUTDOWN方法這時(shí)各個(gè)模塊最后一次釋放內(nèi)存的機(jī)會(huì)。(這個(gè)是對(duì)于CGI和CLI等SAPI,沒(méi)有“下一個(gè)請(qǐng)求”,所以SAPI立刻開(kāi)始關(guān)閉。)

整個(gè)PHP生命周期就結(jié)束了。要注意的是,只有在服務(wù)器沒(méi)有請(qǐng)求的情況下才會(huì)執(zhí)行“啟動(dòng)第一步”和“關(guān)閉第二步”。

SAPI運(yùn)行PHP都經(jīng)過(guò)的幾個(gè)階段

模塊初始化階段(Module init)

即調(diào)用每個(gè)拓展源碼中的的PHP_MINIT_FUNCTION中的方法初始化模塊,進(jìn)行一些模塊所需變量的申請(qǐng),內(nèi)存分配等。

請(qǐng)求初始化階段(Request init)

即接受到客戶端的請(qǐng)求后調(diào)用每個(gè)拓展的PHP_RINIT_FUNCTION中的方法,初始化PHP腳本的執(zhí)行環(huán)境。執(zhí)行PHP腳本

請(qǐng)求結(jié)束(Request Shutdown)

這時(shí)候調(diào)用每個(gè)拓展的PHP_RSHUTDOWN_FUNCTION方法清理請(qǐng)求現(xiàn)場(chǎng),并且ZE開(kāi)始回收變量和內(nèi)存

關(guān)閉模塊(Module shutdown)

Web服務(wù)器退出或者命令行腳本執(zhí)行完畢退出會(huì)調(diào)用拓展源碼中的PHP_MSHUTDOWN_FUNCTION 方法單進(jìn)程SAPI生命周期

CLI/CGI模式的PHP屬于單進(jìn)程的SAPI模式。這類的請(qǐng)求在處理一次請(qǐng)求后就關(guān)閉。也就是只會(huì)經(jīng)過(guò)如下幾個(gè)環(huán)節(jié): 開(kāi)始 - 請(qǐng)求開(kāi)始 - 請(qǐng)求關(guān)閉 - 結(jié)束 SAPI接口實(shí)現(xiàn)就完成了其生命周期。

PHP內(nèi)核了解:生命周期及運(yùn)行模式

多進(jìn)程SAPI生命周期通常PHP是編譯為apache的一個(gè)模塊來(lái)處理PHP請(qǐng)求。 Apache一般會(huì)采用多進(jìn)程模式, Apache啟動(dòng)后會(huì)fork出多個(gè)子進(jìn)程,每個(gè)進(jìn)程的內(nèi)存空間獨(dú)立,每個(gè)子進(jìn)程都會(huì)經(jīng)過(guò)開(kāi)始和結(jié)束環(huán)節(jié) 每個(gè)進(jìn)程的開(kāi)始階段只在進(jìn)程fork出來(lái)以來(lái)后進(jìn)行,在整個(gè)進(jìn)程的生命周期內(nèi)可能會(huì)處理多個(gè)請(qǐng)求。 只有在Apache關(guān)閉或者進(jìn)程被結(jié)束之后才會(huì)進(jìn)行關(guān)閉階段,在這兩個(gè)階段之間會(huì)隨著每個(gè)請(qǐng)求重復(fù)請(qǐng)求開(kāi)始-請(qǐng)求關(guān)閉的環(huán)節(jié)。PHP內(nèi)核了解:生命周期及運(yùn)行模式 多線程的SAPI生命周期

多線程模式和多進(jìn)程中的某個(gè)進(jìn)程類似,不同的是在整個(gè)進(jìn)程的生命周期內(nèi)會(huì)并行的重復(fù)著 請(qǐng)求開(kāi)始-請(qǐng)求關(guān)閉的環(huán)節(jié).

在這種模式下,只有一個(gè)服務(wù)器進(jìn)程在運(yùn)行著,但會(huì)同時(shí)運(yùn)行很多線程,這樣可以減少一些資源開(kāi)銷(xiāo),向Module init和Module shutdown就只需要運(yùn)行一遍就行了,一些全局變量也只需要初始化一次,因?yàn)榫€程獨(dú)具的特質(zhì),使得各個(gè)請(qǐng)求之間方便的共享一些數(shù)據(jù)成為可能。PHP內(nèi)核了解:生命周期及運(yùn)行模式

參考資料:http://www.phppan.com/2011/05/php-cgi/http://www.php-internals.com/book/?p=chapt02/02-01-php-life-cycle-and-zend-engine

標(biāo)簽: PHP
相關(guān)文章: