PHP-FastCGI詳解
一、什麼是 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很簡單,下面是安裝過程:
[[email protected] local]#tar zxvf php-5.2.13.tar.gz [[email protected] local]#gzip -cd php-5.2.13-fpm-0.5.13.diff.gz | patch -d php-5.2.13 -p1 [[email protected] local]#cd php-5.2.13 [[email protected] php-5.2.13]#./configure --prefix=/usr/local/php --enable-fastcgi --enable-fpm [[email protected] php-5.2.13]#make [[email protected] php-5.2.13]#make install [[email protected] 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檢視相關資訊。
[[email protected] php]# netstat -antl|grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN [[email protected] 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當做動態應用伺服器,那麼Nginx其實就是一個反向代理伺服器。Nginx通過反向代理功能實現對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分鐘。
轉自:http://www.itokit.com/2012/0318/73388.html