Nginx與PHP的交互

FastCGI模塊模塊容許nginx同FastCGI協同工做,而且控制哪些參數將被安全傳遞。php

1、CGI和FastCGI簡介

一、什麼是CGI

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

傳統CGI接口方式的主要缺點是性能不好,由於每次HTTP服務器遇到動態程序時都須要從新啓動腳本解析器來執行解析,而後將結果返回給HTTP服務器。這在處理高併發訪問時幾乎是不可用的,另外傳統的CGI接口方式安全性也不好,如今已經不多使用了。html

二、什麼是 FastCGI

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

FastCGI接口方式採nginx


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

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

2、Nginx+FastCGI運行原理

一、運行原理

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須要完成的工做:ruby

一、經過調用fastcgi(庫)的函數經過socket和ningx通訊(讀寫socket是fastcgi內部實現的功能,對wrapper是非透明的)
二、調度thread,進行fork和kill
三、和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動態請求。

二、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的須要加此項。

三、配置信息

關於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端口的意思。

四、總體工做流程:

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。

五、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來源:簡書簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。

相關文章
相關標籤/搜索