FROM: http://ixdba.blog.51cto.com/2895551/806622
一、什麼是 FastCGI
FastCGI是一個可伸縮地、高速地在HTTP server和動態指令碼語言間通訊的介面。多數流行的HTTP server都支援FastCGI,包括Apache、Nginx和lighttpd等,同時,FastCGI也被許多指令碼語言所支援,其中就有PHP。
FastCGI是從CGI發展改進而來的。傳統CGI介面方式的主要缺點是效能很差,因為每次HTTP伺服器遇到動態程式時都需要重新啟動指令碼解析器來執行解析,然後結果被返回給HTTP伺服器。這在處理高並發訪問時,幾乎是停用。另外傳統的CGI介面方式安全性也很差,現在已經很少被使用了。
FastCGI介面方式採用C/S結構,可以將HTTP伺服器和指令碼解析伺服器分開,同時在指令碼解析伺服器上啟動一個或者多個指令碼解析守護進程。當HTTP伺服器每次遇到動態程式時,可以將其直接交付給FastCGI進程來執行,然後將得到的結果返回給瀏覽器。這種方式可以讓HTTP伺服器專一地處理靜態請求或者將動態指令碼伺服器的結果返回給用戶端,這在很大程度上提高了整個應用系統的效能。
二、Nginx+FastCGI運行原理
Nginx不支援對外部程式的直接調用或者解析,所有的外部程式(包括PHP)必須通過FastCGI介面來調用。FastCGI介面在Linux下是socket,(這個socket可以是檔案socket,也可以是ip socket)。為了調用CGI程式,還需要一個FastCGI的wrapper(wrapper可以理解為用於啟動另一個程式的程式),這個wrapper綁定在某個固定socket上,如連接埠或者檔案socket。當Nginx將CGI請求發送給這個socket的時候,通過FastCGI介面,wrapper接納到請求,然後派生出一個新的線程,這個線程調用解譯器或者外部程式處理指令碼並讀取返回資料;接著,wrapper再將返回的資料通過FastCGI介面,沿著固定的socket傳遞給Nginx;最後,Nginx將返回的資料發送給用戶端,這就是Nginx+FastCGI的整個運作過程。詳細的過程,如圖1所示。
圖1 Nginx+FastCGI運行原理
三、spawn-fcgi與PHP-FPM
前面介紹過,FastCGI介面方式在指令碼解析伺服器上啟動一個或者多個守護進程對動態指令碼進行解析,這些進程就是FastCGI進程管理器,或者稱之為FastCGI引擎, spawn-fcgi與PHP-FPM就是支援PHP的兩個FastCGI進程管理器。
下面簡單介紹spawn-fcgi與PHP-FPM的異同。
spawn-fcgi是HTTP伺服器lighttpd的一部分,目前已經獨立成為一個項目,一般與lighttpd配合使用來支援PHP,但是ligttpd的spwan-fcgi在高並發訪問的時候,會出現記憶體流失甚至自動重啟FastCGI的問題。
Nginx是個輕量級的HTTP server,必須藉助第三方的FastCGI處理器才可以對PHP進行解析,因此Nginx+spawn-fcgi的組合也可以實現對PHP的解析,這裡不過多講述。
PHP-FPM也是一個第三方的FastCGI進程管理器,它是作為PHP的一個補丁來開發的,在安裝的時候也需要和PHP源碼一起編譯,也就是說PHP-FPM被編譯到PHP核心中,因此在處理效能方面更加優秀;同時它在處理高並發方面也比spawn-fcgi引擎好很多,因此,推薦Nginx+PHP/PHP-FPM這個組合對PHP進行解析。
FastCGI 的主要優點是把動態語言和HTTP Server分離開來,所以Nginx與PHP/PHP-FPM經常被部署在不同的伺服器上,以分擔前端Nginx伺服器的壓力,使Nginx專一處理靜態請求和轉寄動態請求,而PHP/PHP-FPM伺服器專一解析PHP動態請求。
四、 PHP與PHP-FPM的安裝及最佳化
1.下載安裝包
從www.php.net官方網站下載PHP源碼包,這裡下載的是穩定版php-5.2.13.tar.gz。
從http://php-fpm.org/downloads/下載對應的PHP-FPM源碼包,這裡下載的是php-5.2.13-fpm-0.5.13.diff.gz。
需要注意,在下載軟體包版本時,盡量使PHP和PHP-FPM版本一致,如果版本之間相差太大,可以會出現相容問題。
2.配置安裝環境
安裝PHP需要下面軟體包的支援,如果沒有安裝,請自行安裝。
gcc gcc-c++ libxml2 libxml2-devel autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel
由於各個Linux系統版本的不確定性,讀者也可以在安裝PHP過程中,根據錯誤提示資訊,安裝對應的軟體庫。
3.開始編譯安裝PHP和PHP-FPM
編譯安裝PHP和PHP-FPM很簡單,下面是安裝過程:
[root@localhost local]#tar zxvf php-5.2.13.tar.gz [root@localhost local]#gzip -cd php-5.2.13-fpm-0.5.13.diff.gz | patch -d php-5.2.13 -p1 [root@localhost local]#cd php-5.2.13 [root@localhost php-5.2.13]#./configure --prefix=/usr/local/php --enable-fastcgi --enable-fpm [root@localhost php-5.2.13]#make [root@localhost php-5.2.13]#make install [root@localhost php-5.2.13]cp php.ini-dist /usr/local/php/lib/php.ini
其中,第二步將PHP-FPM作為補丁加入PHP源碼中。
在“./configure”編譯選項中,指定將PHP安裝到/usr/local下,“--enable-fastcgi”是啟用對PHP的FastCGI支援,“--enable-fpm”是啟用對FastCGI模式的fpm支援。
在編譯PHP時可以加入很多編譯選項,但是這裡為了介紹PHP的FastCGI功能沒有加入更多的編譯選項。
4.配置與最佳化PHP-FPM
PHP的全域設定檔是php.ini,在上面的步驟中,已經將此檔案複製到了/usr/local/php/lib/php.ini下。可以根據每個應用需求的不同,對php.ini進行相應的配置。
下面重點介紹PHP-FPM引擎的設定檔。
根據上面指定的安裝路徑,PHP-FPM的預設設定檔為/usr/local/php/etc/php-fpm.conf。
php-fpm.conf是一個XML格式的純文字檔案,其內容很容易看明白。這裡重點介紹幾個重要的配置標籤:
標籤listen_address是配置fastcgi進程監聽的IP地址以及連接埠,預設是127.0.0.1:9000。
<value name="listen_address">127.0.0.1:9000</value>
標籤display_errors用來設定是否顯示PHP錯誤資訊,預設是0,不顯示錯誤資訊,設定為1可以顯示PHP錯誤資訊。
<value name="display_errors">0</value>
標籤user和group用於設定運行FastCGI進程的使用者和使用者組。需要注意的是,這裡指定的使用者和使用者組要和Nginx設定檔中指定的使用者和使用者組一致。
<value name="user">nobody</value>
<value name="group">nobody</value>
標籤max_children用於設定FastCGI的進程數。根據官方建議,小於2GB記憶體的伺服器,可以只開啟64個進程,4GB以上記憶體的伺服器可以開啟200個進程。
<value name="max_children">5</value>
標籤request_terminate_timeout用於設定FastCGI執行指令碼的時間。預設是0s,也就是無限執行下去,可以根據情況對其進行修改。
<value name="request_terminate_timeout">0s</value>
標籤rlimit_files用於設定PHP-FPM對開啟檔案描述符的限制,預設值為1024。這個標籤的值必須和Linux核心開啟檔案數關聯起來,例如要將此值設定為65535,就必須在Linux命令列執行'ulimit -HSn 65536'。
<value name="rlimit_files">1024</value>
標籤max_requests指明了每個children最多處理多少個請求後便會被關閉,預設的設定是500。
<value name="max_requests">500</value>
標籤allowed_clients用於設定允許訪問FastCGI進程解析器的IP地址。如果不在這裡指定IP地址,Nginx轉寄過來的PHP解析請求將無法被接受。
<value name="allowed_clients">127.0.0.1</value>
5.管理FastCGI進程
在配置完php-fpm後,就可以啟動FastCGI進程了。啟動fastcgi進程有兩種方式:
/usr/local/php/bin/php-cgi --fpm 或者 /usr/local/php/sbin/php-fpm start
建議採用第二種方式啟動FastCGI進程。
/usr/local/php/sbin/php-fpm還有其他參數,具體為start|stop|quit|restart|reload|logrotate。
每個啟動參數的含義如下:
start,啟動PHP的FastCGI進程。 stop,強制終止PHP的FastCGI進程。 quit,平滑終止PHP的FastCGI進程。 restart, 重啟PHP的FastCGI進程。 reload, 重新載入PHP的php.ini。 logrotate, 重新啟用log檔案。
reload是個很重要的參數,它可以在PHP的FastCGI進程不中斷的情況下重新載入改動過的php.ini,因此通過php-fpm可以平滑變更FastCGI模式下的PHP設定。
在FastCGI進程啟動後,其監聽的IP地址和連接埠也隨即啟動,可以通過ps和netstat查看相關資訊。
[root@localhost php]# netstat -antl|grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN [root@localhost php]# ps -ef|grep php-cgi root 3567 1 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3568 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3569 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3570 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3571 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3572 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf root 3583 3524 0 17:09 pts/1 00:00:00 grep php-cgi
五、配置Nginx來支援PHP
Nginx的安裝特別簡單,前面已經對此進行了詳細介紹,這裡不再進行講述。下面重點介紹Nginx如何通過php-fpm的FastCGI進程對PHP進行解析處理。
由於Nginx本身不會對PHP進行解析,因此要實現Nginx對PHP的支援,其實是將對PHP頁面的請求交給fastCGI進程監聽的IP地址及連接埠。如果把php-fpm當做Live App伺服器,那麼Nginx其實就是一個反向 Proxy伺服器。Nginx通過反向 Proxy功能實現對PHP的解析,這就是Nginx實現PHP動態解析的原理。
這裡假定Nginx的安裝目錄為/usr/local,則Nginx設定檔的路徑為/usr/local/nginx/conf/nginx.conf。下面是在Nginx下支援PHP解析的一個虛擬機器主機配置執行個體。
server { include port.conf; server_name www.ixdba.net ixdba.net; location / { index index.html index.php; root /web/www/www.ixdba.net; } location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME html$fastcgi_script_name; include fastcgi_params; } }
通過location指令,將所有以php為尾碼的檔案都交給127.0.0.1:9000來處理,而這裡的IP地址和連接埠就是FastCGI進程監聽的IP地址和連接埠。
fastcgi_param指令指定放置PHP動態程式的主目錄,也就是$fastcgi_script_name前面指定的路徑,這裡是/usr/local/nginx/html目錄,建議將這個目錄與Nginx虛擬機器主機指定的根目錄保持一致,當然也可以不一致。
fastcgi_params檔案是FastCGI進程的一個參數設定檔,在安裝Nginx後,會預設產生一個這樣的檔案,這裡通過include指令將FastCGI參數設定檔包含了進來。
接下來,啟動nginx服務。
/usr/local/nginx/sbin/nginx
到此為止,Nginx+PHP已經配置完成。
六、測試Nginx對PHP的解析功能
這裡在/usr/local/nginx/html目錄下建立一個phpinfo.php檔案,內容如下:
<?php phpinfo(); ?>
然後通過瀏覽器訪問http://www.ixdba.net/index.html,預設會在瀏覽器顯示“Welcome to Nginx!”表示Nginx正常運行。
接著在瀏覽器中訪問http://www.ixdba.net/phpinfo.php,如果PHP能夠正常解析,會出現PHP安裝配置以及功能列表統計資訊。
七、執行個體講解Nginx中FastCGI參數的最佳化
在配置完成Nginx+FastCGI之後,為了保證Nginx下PHP環境的高速穩定運行,需要添加一些FastCGI最佳化指令。下面給出一個最佳化執行個體,將下面代碼添加到Nginx主設定檔中的HTTP層級。
fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m inactive=5m; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; fastcgi_cache TEST; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m;
下面是對上述代碼的含義進行介紹。
第一行代碼是為FastCGI緩衝指定一個檔案路徑、目錄結構等級、關鍵字地區儲存時間和非活動刪除時間。
fastcgi_connect_timeout指定串連到後端FastCGI的逾時時間。
fastcgi_send_timeout指定向FastCGI傳送請求的逾時時間,這個值是已經完成兩次握手後向FastCGI傳送請求的逾時時間。
fastcgi_read_timeout指定接收FastCGI應答的逾時時間,這個值是已經完成兩次握手後接收FastCGI應答的逾時時間。
fastcgi_buffer_size用於指定讀取FastCGI應答第一部分需要用多大的緩衝區,這個值表示將使用1個64KB的緩衝區讀取應答的第一部分(應答頭),可以設定為fastcgi_buffers選項指定的緩衝區大小。
fastcgi_buffers指定本地需要用多少和多大的緩衝區來緩衝FastCGI的應答請求。如果一個PHP指令碼所產生的頁面大小為256KB,那麼會為其分配4個64KB的緩衝區來緩衝;如果頁面大小大於256KB,那麼大於256KB的部分會緩衝到fastcgi_temp指定的路徑中,但是這並不是好方法,因為記憶體中的資料處理速度要快於硬碟。一般這個值應該為網站中PHP指令碼所產生的頁面大小的中間值,如果網站大部分指令碼所產生的頁面大小為256KB,那麼可以把這個值設定為“16 16k”、“4 64k”等。
fastcgi_busy_buffers_size的預設值是fastcgi_buffers的兩倍。
fastcgi_temp_file_write_size表示在寫入快取檔案時使用多大的資料區塊,預設值是fastcgi_buffers的兩倍。 fastcgi_cache表示開啟FastCGI緩衝並為其指定一個名稱。開啟緩衝非常有用,可以有效降低CPU的負載,並且防止502錯誤的發生,但是開啟緩衝也會引起很多問題,要視具體情況而定。
fastcgi_cache_valid、fastcgi用來指定應答代碼的緩衝時間,執行個體中的值表示將200和302應答緩衝一個小時,將301應答緩衝1天,其他應答均緩衝1分鐘。