Nginx與PHP的交互

FastCGI模塊模塊允許nginx同FastCGI協同工作,並且控制哪些參數將被安全傳遞。

一、CGI和FastCGI簡介

1、什麼是CGI

CGI 是Web 服務器運行時外部程序的規範接口,按CGI 編寫的程序可以擴展服務器功能。CGI 應用程序能與瀏覽器進行交互,還可通過數據庫API 與數據庫服務器等外部數據源進行通信,從數據庫服務器中獲取數據。格式化爲HTML文檔後,發送給瀏覽器,也可以將從瀏覽器獲得的數據放到數據庫中。幾乎所有服務器都支持CGI,可用任何語言編寫CGI。---引自百度

傳統CGI接口方式的主要缺點是性能很差,因爲每次HTTP服務器遇到動態程序時都需要重新啓動腳本解析器來執行解析,然後將結果返回給HTTP服務器。這在處理高併發訪問時幾乎是不可用的,另外傳統的CGI接口方式安全性也很差,現在已經很少使用了。

2、什麼是 FastCGI

FastCGI是一個可伸縮地、高速地在HTTP server和動態腳本語言間通信的接口。多數流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等。同時FastCGI也被許多腳本語言支持,其中就有PHP。FastCGI是從CGI發展改進而來的。

FastCGI接口方式採


用C/S結構,可以將HTTP服務器和腳本解析服務器分開,同時在腳本解析服務器上啓動一個或者多個腳本解析守護進程。當HTTP服務器每次遇到動態程序時,可以將其直接交付給FastCGI進程來執行,然後將得到的結果返回給瀏覽器。

這種方式的優點:可以讓HTTP服務器專一地處理靜態請求或者將動態腳本服務器的結果返回給客戶端,這在很大程度上提高了整個應用系統的性能。

二、Nginx+FastCGI運行原理

1、運行原理

Nginx不支持對外部程序的直接調用或者解析,所有的外部程序(包括PHP)必須通過FastCGI接口來調用。FastCGI接口在Linux下是socket(這個socket可以是文件socket,也可以是ip socket)。

wrapper:爲了調用CGI程序,還需要一個FastCGI的wrapper(wrapper可以理解爲用於啓動另一個程序的程序),這個wrapper綁定在某個固定socket上,如端口或者文件socket。當Nginx將CGI請求發送給這個socket的時候,通過FastCGI接口,wrapper接收到請求,然後Fork(派生)出一個新的線程,這個線程調用解釋器或者外部程序處理腳本並讀取返回數據;接着,wrapper再將返回的數據通過FastCGI接口,沿着固定的socket傳遞給Nginx;最後,Nginx將返回的數據(html頁面或者圖片)發送給客戶端。這就是Nginx+FastCGI的整個運作過程,如圖1-3所示。

webp

所以,我們首先需要一個wrapper,這個wrapper需要完成的工作:

1、通過調用fastcgi(庫)的函數通過socket和ningx通信(讀寫socket是fastcgi內部實現的功能,對wrapper是非透明的)
2、調度thread,進行fork和kill
3、和application(php)進行通信

Nginx是個輕量級的HTTP server,必須藉助第三方的FastCGI處理器纔可以對PHP進行解析,因此其實這樣看來nginx是非常靈活的,它可以和任何第三方提供解析的處理器實現連接從而實現對PHP的解析(在nginx.conf中很容易設置)。

FastCGI接口方式在腳本解析服務器上啓動一個或者多個守護進程對動態腳本進行解析,這些進程就是FastCGI進程管理器,或者稱爲FastCGI引擎。 spawn-fcgi與PHP-FPM就是支持PHP的兩個FastCGI進程管理器。因此HTTPServer完全解放出來,可以更好地進行響應和併發處理

FastCGI 的主要優點是把動態語言和HTTP Server分離開來,所以Nginx與PHP/PHP-FPM經常被部署在不同的服務器上,以分擔前端Nginx服務器的壓力,使Nginx專一處理靜態請求和轉發動態請求,而PHP/PHP-FPM服務器專一解析PHP動態請求。

2、Nginx+PHP-FPM

PHP-FPM是管理FastCGI的一個管理器,它作爲PHP的插件存在,在安裝PHP要想使用PHP-FPM時在老php的老版本(php5.3.3之前)就需要把PHP-FPM以補丁的形式安裝到PHP中,而且PHP要與PHP-FPM版本一致,這是必須的)

PHP-FPM其實是PHP源代碼的一個補丁,旨在將FastCGI進程管理整合進PHP包中。必須將它patch到你的PHP源代碼中,在編譯安裝PHP後纔可以使用。

PHP5.3.3已經集成php-fpm了,不再是第三方的包了。PHP-FPM提供了更好的PHP進程管理方式,可以有效控制內存和進程、可以平滑重載PHP配置,比spawn-fcgi具有更多優點,所以被PHP官方收錄了。

在./configure的時候帶 –enable-fpm參數即可開啓PHP-FPM。fastcgi已經在php5.3.5的core中了,不必在configure時添加 --enable-fastcgi了。老版本如php5.2的需要加此項。

3、配置信息

關於fastcgi的配置文件,目前fastcgi的配置文件一般放在nginx.conf同級目錄下,配置文件形式,一般有兩種:fastcgi.conf  和 fastcgi_params。不同的nginx版本會有不同的配置文件,這兩個配置文件有一個非常重要的區別:

fastcgi_parames文件中缺少下列配置:
fastcgi_param  SCRIPT_FILENAME    
document_rootfastcgi_script_name;

我們可以打開fastcgi_parames文件加上上述行,也可以在要使用配置的地方動態添加。使得該配置生效。

當我們安裝Nginx和PHP-FPM完後,配置信息:

PHP-FPM的默認配置php-fpm.conf:

listen_address 127.0.0.1:9000 #這個表示php的fastcgi進程監聽的ip地址以及端口start_serversmin_spare_serversmax_spare_servers

Nginx配置運行php: 編輯nginx.conf加入如下語句:

location ~ \.php$ { 
   root html;
   fastcgi_pass 127.0.0.1:9000; #指定了fastcgi進程偵聽的端口,nginx就是通過這裏與php交互的
   fastcgi_index index.php;    include fastcgi_params;
   fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;
}

Nginx通過location指令,將所有以php爲後綴的文件都交給127.0.0.1:9000來處理,而這裏的IP地址和端口就是FastCGI進程監聽的IP地址和端口。

輸入命令 netstat -nlpt|grep php-fpm 會得到:
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1057/php-fpm
這裏的127.0.0.1:9000 就是監聽本機9000端口的意思。

4、整體工作流程:

1)、FastCGI進程管理器php-fpm自身初始化,啓動主進程php-fpm和啓動start_servers個CGI 子進程。主進程php-fpm主要是管理fastcgi子進程,監聽9000端口。fastcgi子進程等待來自Web Server的連接。

2)、當客戶端請求到達Web Server Nginx是時,Nginx通過location指令,將所有以php爲後綴的文件都交給127.0.0.1:9000來處理,即Nginx通過location指令,將所有以php爲後綴的文件都交給127.0.0.1:9000來處理。

3)FastCGI進程管理器PHP-FPM選擇並連接到一個子進程CGI解釋器。Web server將CGI環境變量和標準輸入發送到FastCGI子進程。

4)、FastCGI子進程完成處理後將標準輸出和錯誤信息從同一連接返回Web Server。當FastCGI子進程關閉連接時,請求便告處理完成。

5)、FastCGI子進程接着等待並處理來自FastCGI進程管理器(運行在 WebServer中)的下一個連接。

簡單來說,當需要處理php請求時,nginx的worker進程會將請求移交給php-fpm的worker進程進行處理,也就是最開頭所說的nginx調用了php,其實嚴格得講是nginx間接調用php。

5、Nginx和PHP-FPM的通信方式

Nginx和PHP-FPM的進程間通信有兩種方式

一種是TCP
一種是UNIX Domain Socket.

其中TCP是IP加端口,可以跨服務器。而UNIX Domain Socket不經過網絡,只能用於Nginx跟PHP-FPM都在同一服務器的場景。

用哪種取決於你的PHP-FPM配置:

方式1:
php-fpm.conf: listen = 127.0.0.1:9000
nginx.conf: fastcgi_pass 127.0.0.1:9000;

方式2:
php-fpm.conf: listen = /tmp/php-fpm.sock
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;

其中php-fpm.sock是一個文件,由php-fpm生成,類型是srw-rw----

UNIX Domain Socket可用於兩個沒有親緣關係的進程,是目前廣泛使用的IPC機制,比如X Window服務器和GUI程序之間就是通過UNIX Domain Socket通訊的。這種通信方式是發生在系統內核裏而不會在網絡裏傳播。UNIX Domain Socket和長連接都能避免頻繁創建TCP短連接而導致TIME_WAIT連接過多的問題。對於進程間通訊的兩個程序,UNIX Domain Socket的流程不會走到TCP那層,直接以文件形式,以stream socket通訊。如果是TCP Socket,則需要走到IP層,對於非同一臺服務器上,TCP Socket走的就更多了。


作者:北山學者
鏈接:https://www.jianshu.com/p/eab11cd1bb28
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章