PHP進(jìn)程調(diào)試中出現(xiàn)大量lstat系統(tǒng)調(diào)用,通過編譯realpath_turbo模塊,開啟同時支持open_basedir和realpath_cache_size,優(yōu)化php性能
生產(chǎn)系統(tǒng)架構(gòu)圖
程序和數(shù)據(jù)大概500G,存放在一臺ECS上,開啟了NFS共享給若干臺Nginx服務(wù)器進(jìn)行讀寫,包括共享session也存于NFS分區(qū)。數(shù)據(jù)下一步準(zhǔn)備遷移到OSS.
在系統(tǒng)運(yùn)行中發(fā)現(xiàn)NFS的讀寫效率較低,調(diào)節(jié)NFS的緩存參數(shù)也無改善。例如通過記錄php慢日志,看到大量session_start執(zhí)行很慢:
于是將session存儲方式由文件改為redis,得以解決。
在google搜索NFS+session_start的過程中,發(fā)現(xiàn)了一篇老外的神貼:
文中提到了在NFS下面php的性能問題:由于php程序中需要使用大量的require和include,導(dǎo)致出現(xiàn)大量lstat系統(tǒng)調(diào)用,大大降低程序性能。雖然沒有明確闡述,但我理解,NFS下這個問題會比較明顯。立即在生產(chǎn)系統(tǒng)中采用strace命令進(jìn)行統(tǒng)計分析:
#通過strace跟蹤php-fpm詳細(xì)的lstat調(diào)用規(guī)律#pgrep用法:#-n匹配最新(最近生成的)符合所有其它匹配條件的進(jìn)程#-o匹配最舊(最早生成的)符合所有其它匹配條件的進(jìn)程
strace -c -p $(pgrep -n php-fpm)
果然看到 lstat 占比排第一(由于現(xiàn)在生產(chǎn)系統(tǒng)已經(jīng)調(diào)優(yōu),無法再捕獲結(jié)果,參考上述文檔)
通常調(diào)優(yōu)這個問題可以通過在php.ini(或php-fpm.conf)修改realpath_cache_size和realpath_cache_ttl這兩個參數(shù)即可:
realpath_cache_size: php進(jìn)程所使用的真實(shí)路徑緩沖區(qū)的大小,默認(rèn)16K
realpath_cache_ttl: 緩存時間,默認(rèn)120秒
將以上兩個參數(shù)適當(dāng)加大,即可減少lstat的調(diào)用次數(shù)。
但是當(dāng)php設(shè)置了open_basedir或者開啟了safe_mode時,這兩個參數(shù)將不再生效,見http://bugs.php.net/bug.php?id=52312
open_basedir的作用是限制php的讀取目錄,是必要的安全設(shè)置,當(dāng)然不能取消。要想同時開啟二者,就要引入大神的realpath_turbo模塊了。github地址:https://github.com/Whissi/realpath_turbo
編譯安裝:
cd ~wgethttps://github.com/Whissi/realpath_turbo/archive/master.zip -O realpath_turbo.zipunzip realpath_turbo.zip cd realpath_turbo-master//usr/local/php_5.3.29/bin/phpize ./configure --with-php-config=/usr/local/php_5.3.29/bin/php-config makemake test NO_INTERACTION=1make installecho extension=realpath_turbo.so >> /usr/local/php_5.3.29/lib/php.ini
中間遇到一個編譯錯誤:
/root/realpath_turbo-master/realpath_turbo.c: In function ‘zm_activate_realpath_turbo’:/root/realpath_turbo-master/realpath_turbo.c:43:warning: initialization makes pointer from integer without a cast/root/realpath_turbo-master/realpath_turbo.c:76:error: invalid type argument of ‘unary *’ (have ‘int’)make: *** [realpath_turbo.lo] Error1
打開realpath_turbo.c,去掉74-83行,這段是判斷是否開了safe_mode,如果開了編譯就不通過。因?yàn)闆]有開safe_mode,直接刪掉。
由于使用了php-fpm,將模塊的配置放到了php-fpm.conf中
php_value[open_basedir] = ""php_value[realpath_turbo.disable_dangerous_functions] = 1php_value[realpath_turbo.open_basedir] = "/home1/wwwroot/public_html:/home1/tmp/:/home1/log/"php_value[realpath_cache_size] = 20mphp_value[realpath_cache_ttl] = 3600
``
重啟php-fpm,在phpinfo中看到realpath_turbo模塊已經(jīng)加載。
再次進(jìn)行strace,可以看到lstat已經(jīng)不在占用最多時間,優(yōu)化完成。
更多PHP相關(guān)技術(shù)請搜索千鋒PHP,做真實(shí)的自己,用良心做教育。
互聯(lián)網(wǎng)+時代,時刻要保持學(xué)習(xí),攜手千鋒PHP,Dream It Possible。