1. 程式人生 > >php-fpm優化

php-fpm優化

fpm性能調優 fast-cgi

前言:


最近在騰訊雲買了臺學生機打算搭個博客玩玩,由於空間還在備案中,於是就想著先把環境(LNMP+phpmyadmin+wordpress)部署好,環境很順利,但晚上重新連上雲服務器敲命令時那延時真是叫一個痛苦啊,思來想去覺得八成是內存被耗盡了,於是開始排查優化之旅


查看內存使用情況:

# free -m
             total       used       free     shared    buffers     cached
Mem:           996        933        63          0         74        268
-/+ buffers/cache:        284        712
Swap:            0          0          0


果然,內存幾乎被吃盡,看看哪些亂來的進程吃了我的內存

# ps -A --sort -rss -o comm,pmem,pcpu |uniq -c |head -10

      1 COMMAND         %MEM %CPU
      1 mysqld           9.1  0.0
      1 php-fpm          3.6  0.9
      1 php-fpm          3.4  0.9
      1 php-fpm          3.4  0.8
      1 php-fpm          3.4  0.9
      2 php-fpm          3.4  0.8
      2 php-fpm          3.4  0.6
      1 php-fpm          3.4  0.8
      3 php-fpm          3.4  0.9
 
      
# ps aux | grep php-fpm |wc -l

22


除去以root身份運行的作為管理各個php-fpm進程的 master 進程與grep進程,php-fpm竟然有多達20個占用3.4M的php-fpm進程

先把mysqld放一邊,我們發現很大一部分的內存都被 php-fpm 進程吞了,看來有必要對 php-fpm 做個優化了


優化前,我們有必要了解一下 php-fpm 這個組件,以及php-fpm在 nginx 環境下必不可缺的原因

php-fpm:php-FastCGI Process Manager


我們知道apache與php結合的方式有3種: (找機會對這3種方式做個詳細介紹)

1.配置apache,將php解釋器作為cgi腳本

2.將php直接裝載進apache模塊

3.使用fastcgi

[註]apache默認使用第二種方式


但是,Nginx不支持對外部程序的直接調用或者解析,並且Nginx默認就不支持cgi模式,所以通常Nginx都是使用 fastcgi 的方式與php結合


簡單介紹fast-cgi


fast-cgi在安裝後一旦啟用將 監聽在TCP的某個套接字 上,通常表現為 127.0.0.1:9000 ,於是現在客戶端瀏覽器訪問一個動態網頁(如index.php)時發生的行為:nginx將用戶的http請求接進來,發現用戶請求的是一個php腳本,於是交給fastcgi分析處理,處理完畢後(經過php解釋器解釋與從mysql中取數據)將結果回送給nginx,nginx最後將靜態內容返回給客戶端,所以我們能感受到fast-cgi的一大好處是:將動態腳本的解釋過程從nginx抽出,使得nginx只需專註於與客戶端交互靜態資源,而將動態php腳本分析統統扔給fast-cgi,這樣一來能將動態腳本分析過程從nginx進程中解放出來從而增強nginx的並發能力,二來當php掛了不至於讓nginx一起掛了


介紹完fast-cgi的重要性,只是希望告訴大家雖然現在php-fpm占用了不少的內存空間,但可不能將其打入冷宮,隨隨便便把它們kill或者將php-fpm服務停掉了(這樣你的網站將無法訪問),下面先介紹一下php-fpm配置文件一些重要參數的含義,然後再針對性得做些優化措施


由於我是rpm安裝的php-fpm,所以得先找找相關配置文件

# rpm -qc php-fpm

/etc/logrotate.d/php-fpm
/etc/php-fpm.conf
/etc/php-fpm.d/www.conf
/etc/sysconfig/php-fpm


根據上方ps的提示,我們這裏應當重點優化php-fpm與www相關的參數

# cat /etc/php-fpm.d/www.conf | grep -v "^;" 
 
[www]
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
user = apache
group = apache
pm = dynamic                 # pm模式
pm.max_children = 20             # 最大可創建的子進程的數量
pm.start_servers = 10             # 隨著php-fpm-master一起啟動時創建的子進程數目
pm.min_spare_servers = 5           # 服務器空閑時最小php-fpm進程數量
pm.max_spare_servers = 20           # 服務器空閑時最大php-fpm進程數量
slowlog = /var/log/php-fpm/www-slow.log    # 慢查詢日誌存放路徑
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session


pm的三種模式:


static 表示我們創建固定數量的php-fpm子進程,所以只有 pm.max_children=20 參數生效。啟動php-fpm時會一次性全部啟動21(1個主+20個子)個進程

dynamic 表示啟動進程是動態分配的,子進程的數量隨著請求量的變化以及上述一些參數限制動態變化著

ondemand 該模式下按需分配、銷毀子進程,子進程捆綁了空閑計時器 pm.process_idle_timeout 一旦空閑時間計時器超時就將子進程kill


所以,現在結合php-fpm的默認配置就能解釋:上面用ps輸出發現系統跑著20個php-fpm子進程的原因了

我這個小小站,根據 pm.start_servers=10 剛啟動php-fpm時會產生1個主進程以及10個子進程,當這10個子進程對用戶的大量動態請求忙不過來時,將不斷啟動新的php-fpm子進程以滿足需要,但根據 pm.max_children=20 系統最多只會產生20個子進程,而由於 pm.max_spare_servers=20 假設某時間段內,網站一直沒人訪問,但卻仍需維護著20個子進程,對於像我這種小小站而言,子進程的空閑數量過多了,所以這也是一個優化點,嘮叨這麽多怕大家反而暈頭轉向的,不妨瞅瞅我隨手畫的圖加深理解

技術分享

大家有了這些知識做鋪墊,想必php-fpm的優化技巧不用我說也能猜到一二了吧(如果看官依然懵逼那只能說“看來我這水平還不夠”)


優化方案1:pm模式使用dynamic


配置要點

# vim /etc/php-fpm.d/www.conf
pm = dynamic                 
pm.max_children = 8             
pm.start_servers = 3             
pm.min_spare_servers = 3           
pm.max_spare_servers = 5


重啟 php-fpm 並查看內存占用情況

# service php-fpm restart
停止 php-fpm:                                             [確定]
正在啟動 php-fpm:                                         [確定]


# free -m
             total       used       free     shared    buffers     cached
Mem:           996        410        585          0         90        111
-/+ buffers/cache:        209        787
Swap:            0          0          0


現在內存使用量的確舒服多了,順便看看初始時啟用的子進程數目

# ps aux | grep php-fpm | wc -l
5

5-2=3符合我們上方 pm.start_servers=3 的修改

此時nginx尚未配置頁面緩存,所以可以不斷刷新站點來測試(讓僅有的3個fpm進程忙不過來)看看內存占用情況,下面貼出測試後的現象

# free -m
             total       used       free     shared    buffers     cached
Mem:           996        517        478          0         90        112
-/+ buffers/cache:        314        681
Swap:            0          0          0
# ps aux | grep php-fpm | wc -l
7

系統當前運行的php-fpm子進程個數也符合我們設置的 pm.max_spare_servers=5 (最大空閑進程數)


優化方案2:pm模式使用 ondemand


配置要點

# vim /etc/php-fpm.d/www.conf
pm = ondemand


網站在某刻有大量請求湧入時,內存占用情況

# free -m
             total       used       free     shared    buffers     cached
Mem:           996        765        231          0         90        112
-/+ buffers/cache:        561        435
Swap:            0          0          0


網站平穩時(沒人訪問)系統只跑了個 php-fpm master 進程(因為子進程由於閑置時間過長而被kill掉了)所以此時內存占用也就大大降低啦

# ps aux | grep php-fpm
root     29549  0.0  0.6 317072  6148 ?        Ss   10:16   0:00 php-fpm: master process (/etc/php-fpm.conf)
root     30099  0.0  0.0 103272   884 pts/0    S+   10:28   0:00 grep php-fpm


# free -m                    
             total       used       free     shared    buffers     cached
Mem:           996        414        582          0         91        115
-/+ buffers/cache:        207        789
Swap:            0          0          0


看到這裏,想必各位看官也能自己總結出php-fpm各模式下的優缺點以及php-fpm的優化技巧了吧

本文出自 “cfcgo” 博客,請務必保留此出處http://cfcgo.blog.51cto.com/12425690/1922796

php-fpm優化