一直對php的運行原理一知半解,某個週末查詢了網上的資料,不才有了一些淺顯的理解。特此記錄下來。文章主要分爲兩個模塊進行介紹:php代碼內部運行原理和php運行模式。本文原理介紹的大部分文字是直接引用他人文章,本文是按照個人理解的邏輯將收集的資料重新組織了起來,並添加了個人的一些理解。
這一塊的內容暫時理解的不是很深入,直接引用他人的解釋。
什麼是 Zend ? 什麼是 PHP ?
Zend是語言引擎,PHP內核。PHP是從外層展現的完整系統。咋一聽似乎有點模糊不清,但是其實並不複雜( 看下面).爲了實現一個 web 腳本解釋器,你需要三個部分:
Zend完全參與第一部分,部分參與第二部分;PHP參與第二部分和三部分.他們一起構成完整的PHP包。實際上Zend自己僅僅構成語言核心,用預定義函數實現 PHP 非常基礎部分。而 PHP 包含所有的實際形成語言突出能力的所有模塊。
關於php的擴展等知識以後瞭解後再補充,這裏理解到這個程度就足夠了。
本文所講的運行模式特指使用Apache和nginx等服務器協作的php項目。這裏討論的簡單來說是nginx,Apache是怎麼和php通信的這個問題。
這裏我將收集到的邏輯畫成了一張圖:
對上圖的解釋如下:
SAPI(Server Application Programming Interface)指的是PHP具體應用的編程接口, 就像PC一樣,無論安裝哪些操作系統,只要滿足了PC的接口規範都可以在PC上正常運行, PHP腳本要執行有很多種方式,通過Web服務器,或者直接在命令行下,也可以嵌入在其他程序中。
通常,我們使用Apache或者Nginx這類Web服務器來測試PHP腳本,或者在命令行下通過PHP解釋器程序來執行。 腳本執行完後,Web服務器應答,瀏覽器顯示應答信息,或者在命令行標準輸出上顯示內容。
我們很少關心PHP解釋器在哪裏。雖然通過Web服務器和命令行程序執行腳本看起來很不一樣, 實際上它們的工作流程是一樣的。命令行參數傳遞給PHP解釋器要執行的腳本, 相當於通過url請求一個PHP頁面。腳本執行完成後返回響應結果,只不過命令行的響應結果是顯示在終端上。
腳本執行的開始都是以SAPI接口實現開始的。只是不同的SAPI接口實現會完成他們特定的工作, 例如Apache的mod_php SAPI實現需要初始化從Apache獲取的一些信息,在輸出內容是將內容返回給Apache, 其他的SAPI實現也類似。
而PHP最常用的SAPI提供的2種連接方法:mod_php和mod_fastcgi。
當Apache採用mod_php模式工作時,需要有如下的配置:
也即php作爲Apache的一個子模塊來運行,當通過web訪問php文件時,Apache就會調用php5_module來解析php代碼。
配置加載mod_php模塊後,php便是Apahce進程本身一部分,每個新的Apache子進程都會加載此模塊。這種模式相當於Apache自己就能運行php程序,這樣會有一些弊端:
mod_php 通過嵌入 PHP 解釋器到 Apache 進程中,mod_php 這種嵌入的方式最大的弊端就是內存佔用大,不論是否用到 PHP 解釋器都會將其加載到內存中,典型的就是處理CSS、JS之類的靜態文件是完全沒有必要加載解釋器。參考此篇文章。
CGI全稱是「通用網關接口」(Common Gateway Interface),它可以讓一個客戶端,從網頁瀏覽器向執行在Web服務器上的程序請求數據。 CGI描述了客戶端和這個程序之間傳輸數據的一種標準。 CGI的一個目的是要獨立於任何語言的,所以CGI可以用任何一種語言編寫,只要這種語言具有標準輸入、輸出和環境變量。 如php,perl,tcl等。
CGI運行原理表述如下:
上面的這段話理解可能還是比較抽象,下面我們就通過一次 GET 請求爲例進行詳細說明。
如圖所示,本次請求的流程如下:
FastCGI是Web服務器和處理程序之間通信的一種協議, 是CGI的一種改進方案,FastCGI像是一個常駐(long-lived)型的CGI, 它可以一直執行,在請求到達時不會花費時間去fork一個進程來處理(這是CGI最爲人詬病的fork-and-execute模式)。 正是因爲他只是一個通信協議,它還支持分佈式的運算,所以 FastCGI 程序可以在網站服務器以外的主機上執行,並且可以接受來自其它網站服務器的請求。
FastCGI 是與語言無關的、可伸縮架構的 CGI 開放擴展,將 CGI 解釋器進程保持在內存中,以此獲得較高的性能。 CGI 程序反覆加載是 CGI 性能低下的主要原因,如果 CGI 程序保持在內存中並接受 FastCGI 進程管理器調度, 則可以提供良好的性能、伸縮性、Fail-Over 特性等。原理表述如下:
對FastCGI有一個通俗的解釋:FastCGI事先就需要啓動,而且可以啓動多個CGI模塊,在那裏一直運行等着web發請求,然後再給php解析運算,完成後生成html返回給web後,但是完成後它不會退出,而是繼續等着下一個web請求。參考這裏。
PHP-FPM就是針對於PHP的FastCGI的一種實現,他負責管理一個進程池,來處理來自Web服務器的請求。
但是PHP-FPM僅僅是個「PHP FastCGI 進程管理器」, 它仍會調用PHP解釋器本身來處理請求,PHP解釋器(在Windows下)就是php-cgi.exe。
nginx通常採用PHP-FPM模式運行php程序,它的基本配置如下:
Apache這裏就先不補充了。
php的編程接口SAPI提供兩種連接模式mod_php和mod_fastapi。本文圍繞這個兩種模式展開了相關介紹。參考文章已在文中列出。