先看下PHP的結構圖:php
1)Zend Enginehtml
Zend引擎是PHP實現的核心,提供了語言實現上的基礎設施。例如:PHP的語法實現,腳本的編譯運行環境, 擴展機制以及內存管理等。web
2)Extensionsapache
圍繞着zend引擎,Extensions經過組件式的方式提供各類基礎服務,咱們常見的各類內置函數(如MySQL系列)、標準庫等都是經過Extension來實現,用戶也能夠根據須要實現本身的extension以達到功能擴展、性能優化等目的。編程
3)SAPIsegmentfault
SAPI(Server Application Programming Interface)指的是PHP具體應用的編程接口。就像PC同樣,不管安裝哪些操做系統,只要知足了PC的接口規範均可以在PC上正常運行。瀏覽器
4)架構思想緩存
若是php是一輛車,那麼車的框架就是php自己,Zend是車的引擎(發動機),Ext下面的各類組件就是車的輪子,SAPI能夠看作是公路,車能夠跑在不一樣類型的公路上,而一次php程序的執行就是汽車跑在公路上。所以,咱們須要:性能優異的引擎+合適的車輪+正確的跑道。性能優化
Apache是Apache軟件基金會的一個開放源代碼的Web服務器,Apache支持許多特性,大部分經過模塊擴展實現。服務器
常見的模塊包括mod_auth(權限驗證)、mod_ssl(SSL和TLS支持) mod_rewrite(URL重寫)等。
下圖爲Apache的邏輯構成以及與操做系統的關係:
1)Apache的mod_php5模塊
當PHP須要在Apache服務器下運行時,能夠用mod_php5模塊的形式集成。
此時mod_php5模塊的做用是接收Apache傳遞過來的PHP文件請求,並處理這些請求, 而後將處理後的結果返回給Apache。
2)Apache的運行過程
Apache的運行分爲啓動階段和運行階段。
在運行階段,Apache主要工做是處理用戶的服務請求。
Apache對HTTP的請求能夠分爲鏈接、處理和斷開鏈接三個大的階段。同時也能夠分爲11個小的階段:
Post-Read-Request,URI Translation,Header Parsing,Access Control,Authentication,
Authorization,MIME Type Checking,FixUp,Response,Logging,CleanUp。
3)Apache Hook機制
模塊能夠在Apache的任何一個處理階段中掛接(Hook)上本身的處理函數,從而參與Apache的請求處理過程。
1)CGI
CGI全稱是「通用網關接口」(Common Gateway Interface),描述了客戶端和服務器程序之間傳輸數據的一種標準。它可讓一個客戶端,從網頁瀏覽器向執行在Web服務器上的程序請求數據。CGI用來溝通程序(如PHP, Python, Java)和Web服務器(Apache2, Nginx),理論上任何語言編寫的程序均可以經過CGI來提供Web服務。
好比如今請求的是「index.php」,根據配置文件,Apache知道這個不是靜態文件,須要去找PHP解析器來處理,那麼它會把這個請求簡單處理後交給PHP解析器。Apache會傳url、查詢字符串、POST數據、HTTP header等,而CGI就是規定要傳哪些數據、以什麼樣的格式傳遞給後方處理這個請求的協議。
當web服務器收到「index.php」這個請求後,會啓動對應的CGI程序,這裏就是PHP的解析器。接下來PHP解析器會解析php.ini、載入所有擴展並初始化所有數據結構,而後處理請求,再以CGI規定的格式返回處理後的結果,退出進程,web服務器再把結果返回給瀏覽器。
2)FastCGI
CGI程序存在性能問題,每次請求都會重複「PHP解析器會解析php.ini、載入所有擴展並初始化所有數據結構」這些步驟。
FastCGI是CGI的一種改進方案。FastCGI像是一個常駐(long-live)型的CGI, 它能夠一直執行,在請求到達時不會花費時間去fork一個進程來處理(這是CGI最爲人詬病的fork-and-execute模式)。
FastCGI工做流程的通俗版本以下:
1. Fastcgi會先啓一個master,解析配置文件,初始化執行環境,而後再啓動多個worker。
2. 當請求過來時,master會傳遞給一個worker,而後當即能夠接受下一個請求。這樣就避免了重複的勞動,效率天然是高。
3. 當worker不夠用時,master能夠根據配置預先啓動幾個worker等着。
4. 當空閒worker太多時,也會停掉一些,這樣就提升了性能,也節約了資源。
FastCGI工做流程的專業版本以下:
1. Web Server啓動時載入FastCGI進程管理器(IIS ISAPI或Apache Module)
2. FastCGI進程管理器自身初始化,啓動多個CGI解釋器進程(可見多個php-cgi)並等待來自Web Server的鏈接。
3. 當客戶端請求到達Web Server時,FastCGI進程管理器選擇並鏈接到一個CGI解釋器。Web server將CGI環境變量和標準輸入發送到FastCGI子進程php-cgi。
4. FastCGI子進程完成處理後將標準輸出和錯誤信息從同一鏈接返回Web Server。當FastCGI子進程關閉鏈接時, 請求便告處理完成。FastCGI子進程接着等待並處理來自FastCGI進程管理器(運行在Web Server中)的下一個鏈接。 在CGI模式中,php-cgi在此便退出了。
3)PHP-CGI
PHP-CGI是PHP自帶的FastCGI管理器。
PHP-CGI的不足:
1. php-cgi變動php.ini配置後需重啓php-cgi才能讓新的php-ini生效,不能夠平滑重啓。
2. 直接殺死php-cgi進程,php就不能運行了。(PHP-FPM和Spawn-FCGI就沒有這個問題,守護進程會平滑重新生成新的子進程。)
4)PHP-FPM
PHP-FPM是一個PHP FastCGI管理器,是隻用於PHP的。
PHP-FPM實際上是PHP源代碼的一個補丁,旨在將FastCGI進程管理整合進PHP包中。必須將它patch到你的PHP源代碼中,在編譯安裝PHP後纔可使用。
下圖爲SAPI的簡單示意圖:
SAPI(Server abstraction API),它提供了一個接口,使得PHP能夠和其餘應用進行交互數據。
1)PHP執行的兩個階段,開始和結束
開始階段:
a. 模塊初始化階段(MINIT), 在整個SAPI生命週期內(例如Apache啓動之後的整個生命週期內或者命令行程序整個執行過程當中), 該過程只進行一次
b. 模塊激活階段(RINIT),該過程發生在請求階段, 例如經過url請求某個頁面,則在每次請求以前都會進行模塊激活(RINIT請求開始)
結束階段:
a. 停用模塊(RSHUTDOWN,對應RINIT)
b. 在SAPI生命週期結束(Web服務器退出或者命令行腳本執行完畢退出)時關閉模塊(MSHUTDOWN,對應MINIT)
2)單進程SAPI生命週期
CLI/CGI模式的PHP屬於單進程的SAPI模式。這類的請求在處理一次請求後就關閉。也就是隻會通過以下幾個環節:
開始 - 請求開始 - 請求關閉 - 結束。SAPI接口實現就完成了其生命週期。
a. 啓動:初始化若干全局變量,初始化若干常量,初始化Zend引擎和核心組件,解析php.ini,全局操做函數的初始化,初始化靜態構建的模塊和共享模塊(MINIT),禁用函數和類
b. 激活:激活Zend引擎,激活SAPI,環境初始化,模塊請求初始化
c. 運行:要解析執行的文件,須要作詞法分析、語法分析和中間代碼生成操做,返回此文件的全部中間代碼
d. 關閉:關閉請求的過程是一個若干個關閉操做的集合
e. 結束:flush,關閉Zend引擎
3)多進程SAPI生命週期
一般PHP是編譯爲apache的一個模塊來處理PHP請求。
Apache通常會採用多進程模式, Apache啓動後會fork出多個子進程,每一個進程的內存空間獨立,每一個子進程都會通過開始和結束環節, 不過每一個進程的開始階段只在進程fork出來以來後進行,在整個進程的生命週期內可能會處理多個請求。
4)多線程的SAPI生命週期
多線程模式和多進程中的某個進程相似,不一樣的是在整個進程的生命週期內會並行的重複着 請求開始-請求關閉的環節
SAPI處於PHP整個架構較上層,而真正腳本的執行主要由Zend引擎來完成。
<?php $str = "Hello, World!\n"; echo $str;
a. 如上例中, 傳遞給php程序須要執行的文件, php程序完成基本的準備工做後啓動PHP及Zend引擎, 加載註冊的擴展模塊。
b. 初始化完成後讀取腳本文件,Zend引擎對腳本文件進行詞法分析,語法分析。
c. 編譯成opcode執行。 若是安裝了apc之類的opcode緩存, 編譯環節可能會被跳過而直接從緩存中讀取opcode執行。
不少編程語言都使用lex/yacc或他們的變體(flex/bison)來做爲語言的詞法語法分析生成器, 好比PHP、Ruby、Python以及MySQL的SQL語言實現。
PHP是構建在Zend虛擬機(Zend VM)之上的。PHP的opcode就是Zend虛擬機中的指令。
參考資料:
http://www.cnblogs.com/hongfei/archive/2012/06/12/2547119.html PHP的執行原理/執行流程
http://www.php-internals.com/book/?p=chapt02/02-01-php-life-cycle-and-zend-engine 生命週期和Zend引擎
http://www.php-internals.com/book/?p=chapt02/02-02-01-apache-php-module Apache模塊
http://www.php-internals.com/book/?p=chapt02/02-02-03-fastcgi FastCGI
http://segmentfault.com/q/1010000000256516 FastCgi與PHP-fpm之間是個什麼樣的關係
http://www.cnblogs.com/skynet/p/4173450.html Nginx + CGI/FastCGI + C/Cpp
http://www.php-internals.com/book/?p=chapt02/02-02-00-overview SAPI概述
http://rapheal.sinaapp.com/2013/11/14/php_zend_lex/ PHP-Zend引擎剖析之詞法分析
http://rapheal.sinaapp.com/2013/11/20/php_zend_hello_world/ PHP-Zend引擎剖析之Hello World