一、什么是 FastCGI
FastCGI是一個可伸縮地、高速地在HTTP server和動態(tài)腳本語言間通信的接口。多數(shù)流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同時,F(xiàn)astCGI也被許多腳本語言所支持,其中就有PHP。
FastCGI是從CGI發(fā)展改進而來的。傳統(tǒng)CGI接口方式的主要缺點是性能很差,因為每次HTTP服務器遇到動態(tài)程序時都需要重新啟動腳本解析器來執(zhí)行解析,然后結(jié)果被返回給HTTP服務器。這在處理高并發(fā)訪問時,幾乎是不可用的。另外傳統(tǒng)的CGI接口方式安全性也很差,現(xiàn)在已經(jīng)很少被使用了。
FastCGI接口方式采用C/S結(jié)構(gòu),可以將HTTP服務器和腳本解析服務器分開,同時在腳本解析服務器上啟動一個或者多個腳本解析守護進程。當HTTP服務器每次遇到動態(tài)程序時,可以將其直接交付給FastCGI進程來執(zhí)行,然后將得到的結(jié)果返回給瀏覽器。這種方式可以讓HTTP服務器專一地處理靜態(tài)請求或者將動態(tài)腳本服務器的結(jié)果返回給客戶端,這在很大程度上提高了整個應用系統(tǒng)的性能。
二、Nginx+FastCGI運行原理
Nginx不支持對外部程序的直接調(diào)用或者解析,所有的外部程序(包括PHP)必須通過FastCGI接口來調(diào)用。FastCGI接口在Linux下是socket,(這個socket可以是文件socket,也可以是ip socket)。為了調(diào)用CGI程序,還需要一個FastCGI的wrapper(wrapper可以理解為用于啟動另一個程序的程序),這個wrapper綁定在某個固定socket上,如端口或者文件socket。當Nginx將CGI請求發(fā)送給這個socket的時候,通過FastCGI接口,wrapper接納到請求,然后派生出一個新的線程,這個線程調(diào)用解釋器或者外部程序處理腳本并讀取返回數(shù)據(jù);接著,wrapper再將返回的數(shù)據(jù)通過FastCGI接口,沿著固定的socket傳遞給Nginx;最后,Nginx將返回的數(shù)據(jù)發(fā)送給客戶端,這就是Nginx+FastCGI的整個運作過程。詳細的過程,如圖1所示。
圖1 Nginx+FastCGI運行原理
三、spawn-fcgi與PHP-FPM
前面介紹過,F(xiàn)astCGI接口方式在腳本解析服務器上啟動一個或者多個守護進程對動態(tài)腳本進行解析,這些進程就是FastCGI進程管理器,或者稱之為FastCGI引擎, spawn-fcgi與PHP-FPM就是支持PHP的兩個FastCGI進程管理器。
下面簡單介紹spawn-fcgi與PHP-FPM的異同。
spawn-fcgi是HTTP服務器lighttpd的一部分,目前已經(jīng)獨立成為一個項目,一般與lighttpd配合使用來支持PHP,但是ligttpd的spwan-fcgi在高并發(fā)訪問的時候,會出現(xiàn)內(nèi)存泄漏甚至自動重啟FastCGI的問題。
Nginx是個輕量級的HTTP server,必須借助第三方的FastCGI處理器才可以對PHP進行解析,因此Nginx+spawn-fcgi的組合也可以實現(xiàn)對PHP的解析,這里不過多講述。
PHP-FPM也是一個第三方的FastCGI進程管理器,它是作為PHP的一個補丁來開發(fā)的,在安裝的時候也需要和PHP源碼一起編譯,也就是說PHP-FPM被編譯到PHP內(nèi)核中,因此在處理性能方面更加優(yōu)秀;同時它在處理高并發(fā)方面也比spawn-fcgi引擎好很多,因此,推薦Nginx+PHP/PHP-FPM這個組合對PHP進行解析。
FastCGI 的主要優(yōu)點是把動態(tài)語言和HTTP Server分離開來,所以Nginx與PHP/PHP-FPM經(jīng)常被部署在不同的服務器上,以分擔前端Nginx服務器的壓力,使Nginx專一處理靜態(tài)請求和轉(zhuǎn)發(fā)動態(tài)請求,而PHP/PHP-FPM服務器專一解析PHP動態(tài)請求。
四、 PHP與PHP-FPM的安裝及優(yōu)化
1.下載安裝包
從www.官方網(wǎng)站下載PHP源碼包,這里下載的是穩(wěn)定版php-5.2.13.tar.gz。
從http:///downloads/下載對應的PHP-FPM源碼包,這里下載的是php-5.2.13-fpm-0.5.13.diff.gz。
需要注意,在下載軟件包版本時,盡量使PHP和PHP-FPM版本一致,如果版本之間相差太大,可以會出現(xiàn)兼容問題。
2.配置安裝環(huán)境
安裝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系統(tǒng)版本的不確定性,讀者也可以在安裝PHP過程中,根據(jù)錯誤提示信息,安裝對應的軟件庫。
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.配置與優(yōu)化PHP-FPM
PHP的全局配置文件是php.ini,在上面的步驟中,已經(jīng)將此文件復制到了/usr/local/php/lib/php.ini下。可以根據(jù)每個應用需求的不同,對php.ini進行相應的配置。
下面重點介紹PHP-FPM引擎的配置文件。
根據(jù)上面指定的安裝路徑,PHP-FPM的默認配置文件為/usr/local/php/etc/php-fpm.conf。
php-fpm.conf是一個XML格式的純文本文件,其內(nèi)容很容易看明白。這里重點介紹幾個重要的配置標簽:
標簽listen_address是配置fastcgi進程監(jiān)聽的IP地址以及端口,默認是127.0.0.1:9000。
<value name="listen_address">127.0.0.1:9000</value>
標簽display_errors用來設(shè)置是否顯示PHP錯誤信息,默認是0,不顯示錯誤信息,設(shè)置為1可以顯示PHP錯誤信息。
<value name="display_errors">0</value>
標簽user和group用于設(shè)置運行FastCGI進程的用戶和用戶組。需要注意的是,這里指定的用戶和用戶組要和Nginx配置文件中指定的用戶和用戶組一致。
<value name="user">nobody</value>
<value name="group">nobody</value>
標簽max_children用于設(shè)置FastCGI的進程數(shù)。根據(jù)官方建議,小于2GB內(nèi)存的服務器,可以只開啟64個進程,4GB以上內(nèi)存的服務器可以開啟200個進程。
<value name="max_children">5</value>
標簽request_terminate_timeout用于設(shè)置FastCGI執(zhí)行腳本的時間。默認是0s,也就是無限執(zhí)行下去,可以根據(jù)情況對其進行修改。
<value name="request_terminate_timeout">0s</value>
標簽rlimit_files用于設(shè)置PHP-FPM對打開文件描述符的限制,默認值為1024。這個標簽的值必須和Linux內(nèi)核打開文件數(shù)關(guān)聯(lián)起來,例如要將此值設(shè)置為65535,就必須在Linux命令行執(zhí)行'ulimit -HSn 65536'。
<value name="rlimit_files">1024</value>
標簽max_requests指明了每個children最多處理多少個請求后便會被關(guān)閉,默認的設(shè)置是500。
<value name="max_requests">500</value>
標簽allowed_clients用于設(shè)置允許訪問FastCGI進程解析器的IP地址。如果不在這里指定IP地址,Nginx轉(zhuǎn)發(fā)過來的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還有其他參數(shù),具體為start|stop|quit|restart|reload|logrotate。
每個啟動參數(shù)的含義如下:
- start,啟動PHP的FastCGI進程。
- stop,強制終止PHP的FastCGI進程。
- quit,平滑終止PHP的FastCGI進程。
- restart, 重啟PHP的FastCGI進程。
- reload, 重新加載PHP的php.ini。
- logrotate, 重新啟用log文件。
reload是個很重要的參數(shù),它可以在PHP的FastCGI進程不中斷的情況下重新加載改動過的php.ini,因此通過php-fpm可以平滑變更FastCGI模式下的PHP設(shè)置。
在FastCGI進程啟動后,其監(jiān)聽的IP地址和端口也隨即啟動,可以通過ps和netstat查看相關(guān)信息。
- [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的安裝特別簡單,前面已經(jīng)對此進行了詳細介紹,這里不再進行講述。下面重點介紹Nginx如何通過php-fpm的FastCGI進程對PHP進行解析處理。
由于Nginx本身不會對PHP進行解析,因此要實現(xiàn)Nginx對PHP的支持,其實是將對PHP頁面的請求交給fastCGI進程監(jiān)聽的IP地址及端口。如果把php-fpm當做動態(tài)應用服務器,那么Nginx其實就是一個反向代理服務器。Nginx通過反向代理功能實現(xiàn)對PHP的解析,這就是Nginx實現(xiàn)PHP動態(tài)解析的原理。
這里假定Nginx的安裝目錄為/usr/local,則Nginx配置文件的路徑為/usr/local/nginx/conf/nginx.conf。下面是在Nginx下支持PHP解析的一個虛擬主機配置實例。
- server {
- include port.conf;
- server_name www. ;
-
- location / {
- index index.html index.php;
- root /web/www/www.;
- }
-
- 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進程監(jiān)聽的IP地址和端口。
fastcgi_param指令指定放置PHP動態(tài)程序的主目錄,也就是$fastcgi_script_name前面指定的路徑,這里是/usr/local/nginx/html目錄,建議將這個目錄與Nginx虛擬主機指定的根目錄保持一致,當然也可以不一致。
fastcgi_params文件是FastCGI進程的一個參數(shù)配置文件,在安裝Nginx后,會默認生成一個這樣的文件,這里通過include指令將FastCGI參數(shù)配置文件包含了進來。
接下來,啟動nginx服務。
/usr/local/nginx/sbin/nginx
到此為止,Nginx+PHP已經(jīng)配置完成。
六、測試Nginx對PHP的解析功能
這里在/usr/local/nginx/html目錄下創(chuàng)建一個phpinfo.php文件,內(nèi)容如下:
<?php phpinfo(); ?>
然后通過瀏覽器訪問http://www./index.html,默認會在瀏覽器顯示“Welcome to Nginx!”表示Nginx正常運行。
接著在瀏覽器中訪問http://www./phpinfo.php,如果PHP能夠正常解析,會出現(xiàn)PHP安裝配置以及功能列表統(tǒng)計信息。
七、實例講解Nginx中FastCGI參數(shù)的優(yōu)化
在配置完成Nginx+FastCGI之后,為了保證Nginx下PHP環(huán)境的高速穩(wěn)定運行,需要添加一些FastCGI優(yōu)化指令。下面給出一個優(yōu)化實例,將下面代碼添加到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緩存指定一個文件路徑、目錄結(jié)構(gòu)等級、關(guān)鍵字區(qū)域存儲時間和非活動刪除時間。
fastcgi_connect_timeout指定連接到后端FastCGI的超時時間。
fastcgi_send_timeout指定向FastCGI傳送請求的超時時間,這個值是已經(jīng)完成兩次握手后向FastCGI傳送請求的超時時間。
fastcgi_read_timeout指定接收FastCGI應答的超時時間,這個值是已經(jīng)完成兩次握手后接收FastCGI應答的超時時間。
fastcgi_buffer_size用于指定讀取FastCGI應答第一部分需要用多大的緩沖區(qū),這個值表示將使用1個64KB的緩沖區(qū)讀取應答的第一部分(應答頭),可以設(shè)置為fastcgi_buffers選項指定的緩沖區(qū)大小。
fastcgi_buffers指定本地需要用多少和多大的緩沖區(qū)來緩沖FastCGI的應答請求。如果一個PHP腳本所產(chǎn)生的頁面大小為256KB,那么會為其分配4個64KB的緩沖區(qū)來緩存;如果頁面大小大于256KB,那么大于256KB的部分會緩存到fastcgi_temp指定的路徑中,但是這并不是好方法,因為內(nèi)存中的數(shù)據(jù)處理速度要快于硬盤。一般這個值應該為站點中PHP腳本所產(chǎn)生的頁面大小的中間值,如果站點大部分腳本所產(chǎn)生的頁面大小為256KB,那么可以把這個值設(shè)置為“16 16k”、“4 64k”等。
fastcgi_busy_buffers_size的默認值是fastcgi_buffers的兩倍。
fastcgi_temp_file_write_size表示在寫入緩存文件時使用多大的數(shù)據(jù)塊,默認值是fastcgi_buffers的兩倍。
fastcgi_cache表示開啟FastCGI緩存并為其指定一個名稱。開啟緩存非常有用,可以有效降低CPU的負載,并且防止502錯誤的發(fā)生,但是開啟緩存也會引起很多問題,要視具體情況而定。
fastcgi_cache_valid、fastcgi用來指定應答代碼的緩存時間,實例中的值表示將200和302應答緩存一個小時,將301應答緩存1天,其他應答均緩存1分鐘。
本文出自 “技術(shù)成就夢想” 博客,請務必保留此出處http://ixdba.blog.51cto.com/2895551/806622
|