天天看點

《高性能Linux伺服器建構實戰》——1.7節實戰Nginx與PHP(FastCGI)的安裝、配置與優化

1.7.1 什麼是 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伺服器專一地處理靜态請求或者将動态腳本伺服器的結果傳回給用戶端,這在很大程度上提高了整個應用系統的性能。

1.7.2 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-3所示。

1.7.3 spawn-fcgi與php-fpm

前面介紹過,fastcgi接口方式在腳本解析伺服器上啟動一個或者多個守護程序對動态腳本進行解析,這些程序就是fastcgi程序管理器,或者稱為fastcgi引擎。 spawn-fcgi與php-fpm就是支援php的兩個fastcgi程序管理器。

下面簡單介紹spawn-fcgi與php-fpm的異同。

《高性能Linux伺服器建構實戰》——1.7節實戰Nginx與PHP(FastCGI)的安裝、配置與優化

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核心中,是以在處理性能方面更加優秀。同時php-fpm在處理高并發方面也比spawn-fcgi引擎好很多,是以,推薦使用nginx+php/php-fpm這個組合對php進行解析。

fastcgi 的主要優點是把動态語言和http server分離開來,是以nginx與php/php-fpm經常被部署在不同的伺服器上,以分擔前端nginx伺服器的壓力,使nginx專一處理靜态請求和轉發動态請求,而php/php-fpm伺服器專一解析php動态請求。

1.7.4 php與php-fpm的安裝及優化

1.下載下傳安裝包

從www.php.net官方網站下載下傳php源碼包,這裡下載下傳的是穩定版php-5.2.13.tar.gz。

需要注意,在下載下傳軟體包版本時,盡量使php和php-fpm版本一緻,如果版本之間相差太大,可能會出現相容的問題。

2.配置安裝環境

安裝php需要下面軟體包的支援,如果沒有安裝,請自行安裝。

由于各個linux系統版本有不确定性,讀者也可以在安裝php過程中,根據錯誤提示資訊,安裝對應的軟體庫。

3.開始編譯安裝php和php-fpm

編譯安裝php和php-fpm很簡單,下面是安裝過程:

其中,第二步将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。

5.管理fastcgi程序

在配置完php_fpm後,就可以啟動fastcgi程序了。啟動fastcgi程序有以下兩種方式:

建議采用第二種方式啟動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檢視相關資訊。

1.7.5 配置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解析的一個虛拟主機配置執行個體。

通過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服務。

到此為止,nginx+php已經配置完成。

1.7.6 測試nginx對php的解析功能

這裡在/usr/local/nginx/html目錄下建立一個phpinfo.php檔案,内容如下:

1.7.7 優化nginx中fastcgi參數的執行個體

在配置完成nginx+fastcgi之後,為了保證nginx下php環境的高速穩定運作,需要添加一些fastcgi優化指令。下面給出一個優化執行個體,将下面代碼添加到nginx主配置檔案中的http層級。

下面對上述代碼的含義進行介紹。

第一行代碼是為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用來指定應答代碼的緩存時間。執行個體中的值表示将200和302應答緩存一個小時,将301應答緩存1天,其他應答均緩存1分鐘。