天天看點

Nginx系列2之Nginx+php 

what's FastCGi

  FastCGI是一個可伸縮,高速的在HTTP server和動态腳本語言間通信的接口。FastCGI支援多種腳本語言和HTTP server。

  FCGI是由CGI發展改進而來的。傳統的CGI接口方式的性能很差。每次HTTP伺服器遇到動态程式時都需要重新啟動腳本解釋器來執行解析,然後将結果傳回給HTTP伺服器,這在處理高并發通路時幾乎是不可用的。另外傳統的CGI接口方式安全性也很差,現在很少使用了。

  FCGI接口方式采用C/S結構,可以将HTTP伺服器和腳本解釋器分開,同時在腳本解釋器上啟動一個或者多個腳本解釋器守護程序。當HTTP伺服器遇到動态程式時,可以将其直接傳遞給FCGI程序來執行,然後将得到的結果傳回給浏覽器。這種方式可以讓HTTP伺服器專一的處理靜态請求或者動态腳本的結果傳回給用戶端,這就很大程度上提高了響應速度。

Nginx + FCGI運作原理

  Nginx 不支援對外部程式的直接調用或者解析,所有的外部程式(包括PHP)必須通過FCGI接口來調用。FCGI接口在linux是socket(這個socket是檔案socket,也可以是ip socket)。為了調用CGI程式,還需要一個FCGI的wrapper(wrapper可以了解為啟動另一個程式的程式)。這個wrapper綁定在某個固定的socket上,如端口或者檔案的socket,當Nginx将cgi請求發送給這個socket的時候,通過FCGI接口,wrapper接收到請求,然後派生出一個新的線程,這個線程調用解釋器或者外部程式處理腳本并讀取資料,接着,wrapper将傳回的資料通過FCGi接口,沿着固定的socket傳給Nginx,最終,NGinx将傳回的資料發送給用戶端,這就是Nginx+FCGi的運作流程。如圖所示:

Nginx系列2之Nginx+php 

spawn-fcgi 和 php-fpm

  FCGI接口方式在腳本解析伺服器上啟動一個或者多個守護程序對動态腳本進行解析,這些程序就是FastCGI程序管理器,或者稱為fastCgi引擎,spawn-fcgi 和 PHP-FPM就是支援php的兩個Fcgi程序管理器。

  span-fcgi是HTTP伺服器lighttpd的一部分,目前是獨立的一個項目,一般與lighttpd配合使用來支援PHP,但是lighttpd的spwan-fcgi在高并發通路的時候,會出現記憶體洩漏甚至自動重新開機FastCGI的問題

  Nginx是個輕量級的HTTPserver,必須借助第三方的FCGI處理器才可以對PHP進行解析。

  PHP-FPM是一個第三方的FCGI程序管理器,它是PHP的一個更新檔來開發的,在安裝的時候也需要和PHP源碼一起編譯,也就是說PHP-FPM被編譯到PHP核心中,是以處理性能方面更加優秀,同僚PHP-FPM在處理高并發方面也比spawn-fcgi引擎好很多,是以推薦NGINX+PHP-FPM組合。

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

那麼就部署它們吧

  php下載下傳位址: http://php.net

  php-fpm下載下傳位址:http://php-fpm.org/downloads/

  我這裡下載下傳的php是php-5.5.38

  安裝之前,把依賴包都安裝好,采用yum安裝 :

yum -y install gcc gcc++ libxml2 libxml2-devel autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel glibc-devel glib2 glib2-devel
           

安裝好依賴包後,安裝php

./configure --prefix=/usr  /local/php --enable-fpm --enable-fastcgi(可能會提示沒有這個選項)
    make && make install 
           

  編譯沒有問題後,我們開始配置和優化php-fpm,php全局配置檔案是php.ini,編譯後是在/etc/php.ini這下面。

重點介紹php-fpm引擎的配置檔案

php-fpm配置檔案也在/etc/php-fpm.conf下面,預設情況下會把/etc/php-fpm.d/www.conf 的配置檔案include進去。

我們在www.conf裡面看看以下幾項:
    listen = 127.0.0.1:9000 #監聽了本地9k端口
    user = nginx     #運作使用者
    group = nginx
    pm.max_children = 50        # 設定fcgi的程序數,官方建議小于2G記憶體開啟64個,4G可以開200個
    request_terminate_timeout = 0   # 用于設定FCGI執行腳本的時間,預設是0秒,也就是五險的執行下去,可以更加情況改
    rlimit_files = 1024 #設定PHP-FPM 打開檔案描述符的限制,這個值要和linux核心打開檔案數關聯起來,例如,要将此值設定為65535,就必須在linux指令上執行ulimit -HSN 65536
    pm.max_requests = 500  設定處理多少個請求後便會關閉,預設是500,
    listen.allowed_clients = 127.0.0.1    # 設定允許通路FCGI程序解析器的IP位址,如果不在IP位址,将無法接受Nginx轉發過來的php解析請求。
           

了解完上訴配置後,就可以啟動FastCGI了,啟動指令如下:

[[email protected] ~]# php-fpm        啟動php-fpm
           

如果有像這樣的報錯:

[[email protected] php]# php-cgi 
    PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/redis.so' - /usr/lib64/php/modules/redis.so: undefined symbol: igbinary_unserialize in Unknown on line 0
           

那麼在/etc/php.ini把這行注釋掉啟動就可以了:

;  extension=/usr/lib64/php/modules/redis.so
           

Notice

如果是php7.0版本以上的,可以使用以下指令安裝redis

[[email protected] ~]# pecl install redis
pecl/redis requires PHP (version >= 7.0.0, version <= 7.1.0, excluded versions: 6.0.0),              installed version is 5.5.32
No valid packages found
install failed
           

配置nginx來支援php

我們切換到nginx配置檔案目錄下,發現有個default.conf的模版檔案,我們copy一份來修改後即可用,指令如下:

[[email protected] ~]# cd /etc/nginx/conf.d/
[[email protected] conf.d]# ls
default.conf
[[email protected] conf.d]# cp default.conf web1.conf
[[email protected] conf.d]# mv default.conf default.cf    # 避免預設配置影響nginx運作
[[email protected] conf.d]# vim web1.conf 
# 寫入以下内容:
server {
    listen       80;
    server_name  web1.test.com;
    charset utf8;
    location / {
        root   /var/www/html;
        index  index.html index.htm;
    }
    error_page  404              /404.html;
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    location ~ \.php$ {
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/html/$fastcgi_script_name;;
        include        fastcgi_params;
    }
}
           

參數解釋

  • location 正則比對到以php結尾的到這裡解析,
  • root 指明了網站目錄
  • fastcgi_pass 指明了用哪裡的php-fpm來解析
  • fastcgi_index 指明首頁
  • fastcgi_param 指明的是php動态程式的主目錄,/scripts也就是$fastcgi_script_name前面指定的路徑,我們一般在這裡寫網站根目錄的路徑,比如我們的路徑是 /var/www/html。

測試php+nginx是否正常工作

在網站根目錄下面建立Index.php檔案,寫入一些内容,指令如下:

/var/www/html/index.html的内容:
<h1>
    <span> hello, this is test page </span>
</h1>
/var/www/html/phpinfo.php内容:
<?php phpinfo(); ?>
           

我們通路http://ip/如果出現自定義頁面,那麼就成功了。

通路http://ip/phpinfo.php 出現php安裝資訊,那麼也算成功了。

優化Nginx和FastCgi參數

我們在nginx配置檔案裡面的http段内添加一下内容,比如我們現在使用的web1.conf檔案,那麼我就在web1.conf裡面添加以下内容:

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_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
           

參數解釋

  • fastcgi_connect_timeout 300;` 值連接配接到後端FastCGI的逾時時間
  • fastcgi_send_timeout 300; 指向Fastcgi 傳送請求的逾時時間,這個值是已經完成了2次握手後向FastCGI應答的逾時時間
  • fastcgi_read_timeout 300; 指向接收FastCGI應答的逾時時間,這個是已經完成2次握手後接收FastCGI應答的逾時時間
  • fastcgi_buffer_size 64k; 用于指定讀取FastCGI。 應答第一部分需要多大的緩沖區,這個值表示将使用1個64KB的緩沖區讀取應答的第一部分(應答頭),可以設定Fastcgi_buffers選項指定的緩沖區大小。
  • fastcgi_buffers 4 64k; 指定本地需要多少和多大的緩沖區緩沖FastCGI的應答請求。如果一個PHP腳本所産生的頁面大小為256KB,那麼就會為其配置設定4個64KB的緩沖區來緩存,如果頁面大小大于256KB,那麼大于256KB的部分會緩存到Fastcgi_temp指定的路徑中。但是這個不是好辦法。因為記憶體中的資料處理速度大于硬碟,一般這個值應該為站點中的php腳本所産生的頁面大小的中間值,如果站點大部分腳本所産生的頁面大小為256KB,那麼可以把這個值設定為16 16K,或者4 64KB。。
  • fastcgi_busy_buffers_size 128k; 預設值是fastcgi_buffers的兩 倍
  • fastcgi_temp_file_write_size 128k; 表示寫入緩存檔案時使用多大的資料塊,預設是fastcgi_buffers的兩倍。
  • 開啟緩存後:

    fastcgi_cache_valid 200 302 1h;将http狀态碼是200的和302的緩存一小時,301的緩存一天,其他的緩存一分鐘

  • fastcgi_cache_valid 301 1d;
  • fastcgi_cache_valid any 1m;

寫完以上參數後,儲存退出重新開機服務。