最近項目中本地測試環境遇到了windows環境下的nginx使用file_get_contents/curl訪問php文件致使的阻塞問題,一直在找解決的方案,這個問題研究了三天終於找到了解決方案,特別由於這個我也對php的運行原理產生了興趣,因此這裏對此進行必定程度的記錄,可能會有錯漏的地方,歡迎指正。php
要了解php的運行原理,首先要了解下面幾個概念:前端
CGI:nginx
CGI的英文是(COMMON GATEWAY INTERFACE)公共網關接口,它的做用就是幫助服務器與語言通訊,這裏就是nginx和php進行通訊,由於nginx和php的語言不通,所以須要一個溝通轉換的過程,而CGI就是這個溝通的協議。web
nginx服務器在接受到瀏覽器傳遞過來的數據後,若是請求的是靜態的頁面或者圖片等無需動態處理的則會直接根據請求的url找到其位置而後返回給瀏覽器,這裏無需php參與,可是若是是一個動態的頁面請求,這個時候nginx就必須與php通訊,這個時候就會須要用到cgi協議,將請求數據轉換成php能理解的信息,而後php根據這些信息返回的信息也要經過cgi協議轉換成nginx能夠理解的信息,最後nginx接到這些信息再返回給瀏覽器。apache
fast-cgi:windows
傳統的cgi協議在每次鏈接請求時,會開啓一個進程進行處理,處理完畢會關閉該進程,所以下次鏈接,又要再次開啓一個進程進行處理,所以有多少個鏈接就有多少個cgi進程,這也就是爲何傳統的cgi會顯得緩慢的緣由,所以過多的進程會消耗資源和內存。瀏覽器
而fast-cgi則是一個進程能夠處理多個請求,和上面的cgi協議徹底不同,cgi是一個進程只能處理一個請求,這樣就會致使大量的cgi程序,所以會給服務器帶來負擔。服務器
php-cgi:markdown
php-cgi是php提供給web serve也就是http前端服務器的cgi協議接口程序,當每次接到http前端服務器的請求都會開啓一個php-cgi進程進行處理,並且開啓的php-cgi的過程當中會先要重載配置,數據結構以及初始化運行環境,若是更新了php配置,那麼就須要重啓php-cgi才能生效,例如phpstudy就是這種狀況。數據結構
php-fpm:
php-fpm是php提供給web serve也就是http前端服務器的fastcgi協議接口程序,它不會像php-cgi同樣每次鏈接都會從新開啓一個進程,處理完請求又關閉這個進程,而是容許一個進程對多個鏈接進行處理,而不會當即關閉這個進程,而是會接着處理下一個鏈接。它能夠說是php-cgi的一個管理程序,是對php-cgi的改進。
php-fpm會開啓多個php-cgi程序,而且php-fpm常駐內存,每次web serve服務器發送鏈接過來的時候,php-fpm將鏈接信息分配給下面其中的一個子程序php-cgi進行處理,處理完畢這個php-cgi並不會關閉,而是繼續等待下一個鏈接,這也是fast-cgi加速的原理,可是因爲php-fpm是多進程的,而一個php-cgi基本消耗7-25M內存,所以若是鏈接過多就會致使內存消耗過大,引起一些問題,例如nginx裏的502錯誤。
同時php-fpm還附帶一些其餘的功能:
例如平滑過渡配置更改,普通的php-cgi在每次更改配置後,須要從新啓動才能初始化新的配置,而php-fpm是不須要,php-fpm分將新的鏈接發送給新的子程序php-cgi,這個時候加載的是新的配置,而原先正在運行的php-cgi仍是使用的原先的配置,等到這個鏈接後下一次鏈接的時候會使用新的配置初始化,這就是平滑過渡。
可能上面文字敘述很難理解,下面用圖形來簡要的說明瀏覽器請求web服務器的過程、cgi以及fastcgi,以及php-cgi和php-fpm之間的區別和聯繫:
上面是使用php-fpm的動態頁面的過程,下面補充沒有普通cgi協議的狀況;
這裏的web server能夠是nginx,也能夠是IIS和apache等http服務器,也能夠成爲網站服務器或者前端服務器。
原文地址:https://blog.csdn.net/belen_xue/article/details/65950658