一. 概述
項目驗收階段, 需要對部分PHP接口進行性能測試, 性能測試環(huán)境架構(gòu)為如下所示:
使用ab壓力測試, 2000請求, 500并發(fā), 發(fā)現(xiàn)性能瓶頸在Apache和PHP之間, 對底層原理不了解, 調(diào)優(yōu)過程曲折迷離, 將其記錄下來, 日后再仔細琢磨!
- PHP版本: 7.0.4
- Apache版本: 2.4.18
- MySQL版本: 5.7.11
二. 優(yōu)化Linux內(nèi)核參數(shù)
vim /etc/sysctl.conf
, 在末尾加入如下內(nèi)容
net.core.somaxconn = 2048
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 20000
net.ipv4.ip_local_port_range = 5000 65000
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_orphans = 131072
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_syncookies = 1
fs.nr_open = 1000000
執(zhí)行sysctl -p
生效
需要根據(jù)自己機器配置做相應(yīng)的調(diào)節(jié)
參考博客如下
https://blog.csdn.net/aresiii/article/details/48374987
https://blog.csdn.net/leonpengweicn/article/details/50477530
https://blog.csdn.net/tallercc/article/details/52823075
三. 優(yōu)化Apache
1. Apache工作模式調(diào)優(yōu),
- 查看Apache工作模式
/usr/local/apache2/bin/apachectl -l
core.c
mod_so.c
http_core.c
event.c(event模式)
- 在主配置文件里開啟mpm
vim /usr/local/apache2/conf/httpd.conf
Include conf/extra/httpd-mpm.conf
- 根據(jù)各自的不同的工作修改mpm中對應(yīng)的配置
vim /usr/local/apache2/conf/extra/httpd-mpm.conf
參考博客:
https://blog.csdn.net/STFPHP/article/details/52954303
http://blog.jobbole.com/91920/
http://www.cnblogs.com/fazo/p/5588644.html
2. Apache 重寫機制調(diào)優(yōu)
將index.php重寫規(guī)則寫到Apache配置文件里, 而不是使用.htaccess文件, 禁用.htacess文件讀取, 配置如下
DocumentRoot "/home/uar/uar/codes/web/uar-web/public"
<Directory "/home/uar/uar/codes/web/uar-web/public">
#Options Indexes FollowSymLinks
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# AllowOverride FileInfo AuthConfig Limit
# 不查找.htaccess文件
AllowOverride None
# 重寫需要配置該條
Options FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
3. 開啟KeepAlive On長連接
Include conf/extra/httpd-default.conf
根據(jù)需要調(diào)節(jié)配置文件
四. PHP調(diào)優(yōu)
本次壓測系統(tǒng)使用Laravel5.2編寫, PHP版本為7.0.4
強烈推薦看<strong>鳥哥博客</strong>:
http://www.laruence.com/2015/12/04/3086.html
https://blog.csdn.net/qq_36031499/article/details/53911734
1. 開啟opcache(性能提高了5倍, 強烈推薦)
在php.ini最后加入如下配置, 開啟opcache
zend_extension="opcache.so"
; 開關(guān)打開
opcache.enable=1
; ; 設(shè)置共享內(nèi)存大小, 單位為:Mb
opcache.memory_consumption=2048
; 刹悴;如果啟用侥钳,那么 OPcache 會每隔 opcache.revalidate_freq 設(shè)定的秒數(shù) 檢查腳本是否更新瞻鹏。 如果禁用此選項跨跨,你必須使用 opcache_reset() 或者 opcache_invalidate() 函數(shù)來手動重置 OPcache嫩舟,也可以 通過重啟 Web 服務(wù)器來使文件系統(tǒng)更改生效姆钉。
opcache.validate_timestamps=1
;opcache.enable_cli=0
;求得uar項目PHP文件為35846, opcache.max_accelerated_files應(yīng)該比項目文件數(shù)大
opcache.max_accelerated_files=50000
opcache.interned_strings_buffer=64
opcache.fast_shutdown=1
參考博客: https://www.abcdocker.com/abcdocker/2151
opcache文檔: https://www.scalingphpbook.com/blog/2014/02/14/best-zend-opcache-settings.html
2. Laravel層面的優(yōu)化
- 由于是接口性能測試, 去掉沒有必要的中間件
- 關(guān)掉debug
- 將無用的日志打印去掉
- 生成配置文件緩存
.....
ab相關(guān)博客
https://blog.linuxeye.cn/124.html
https://blog.csdn.net/officercat/article/details/49891809
https://www.cnblogs.com/hedy-x/p/8065802.html
五. MySQL相關(guān)調(diào)優(yōu)文檔
https://www.cnblogs.com/angryprogrammer/p/6667741.html
https://segmentfault.com/a/1190000011687570
https://segmentfault.com/a/1190000014108616
https://blog.csdn.net/linuxlsq/article/details/52606255
附錄: 關(guān)于opcache的配置說明
參考博客: https://gywbd.github.io/posts/2016/1/best-config-for-zend-opcache.html
zend opcache的最佳設(shè)置
在網(wǎng)上無意中看到的一篇文章匙睹,這哥們非常簡潔地談?wù)摿藌end opcache的最佳設(shè)置埠啃,他說他為此花了大量的時間探索zend opcache的每個設(shè)置選項的細節(jié)送讲,甚至是閱讀它的源代碼奸笤,并且在自己的項目中實踐(一個每天有117 million的HTTP請求的應(yīng)用)。個人覺得這種文章相當(dāng)有指導(dǎo)意義哼鬓,所以特地把它的設(shè)置方式摘譯如下(格式有些修改):
opcache.revalidate_freq
這個選項用于設(shè)置緩存的過期時間(單位是秒)监右,當(dāng)這個時間達到后,opcache會檢查你的代碼是否改變异希,如果改變了PHP會重新編譯它健盒,生成新的opcode,并且更新緩存称簿。值為“0”表示每次請求都會檢查你的PHP代碼是否更新(這意味著會增加很多次stat系統(tǒng)調(diào)用扣癣,譯注:stat系統(tǒng)調(diào)用是讀取文件的狀態(tài),這里主要是獲取最近修改時間憨降,這個系統(tǒng)調(diào)用會發(fā)生磁盤I/O父虑,所以必然會消耗一些CPU時間,當(dāng)然系統(tǒng)調(diào)用本身也會消耗一些CPU時間)授药∈亢浚可以在開發(fā)環(huán)境中把它設(shè)置為0,生產(chǎn)環(huán)境下不用管烁焙,因為下面會介紹另外一個設(shè)置選項航邢。
opcache.validate_timestamps
當(dāng)這個選項被啟用(設(shè)置為1),PHP會在opcache.revalidate_freq設(shè)置的時間到達后檢測文件的時間戳(timestamp)骄蝇。
如果這個選項被禁用(設(shè)置為0)膳殷,opcache.revalidate_freq會被忽略,PHP文件永遠不會被檢查九火。這意味著如果你修改了你的代碼赚窃,然后你把它更新到服務(wù)器上,再在瀏覽器上請求更新的代碼對應(yīng)的功能岔激,你會看不到更新的效果勒极,你必須得重新加載你的PHP(使用kill -SIGUSR2強制重新加載)。
這個設(shè)定是不是有些蛋疼虑鼎,但是我強烈建議你在生產(chǎn)環(huán)境中使用辱匿,why键痛?因為當(dāng)你在更新服務(wù)器代碼的時候,如果代碼較多匾七,更新操作是有些延遲的絮短,在這個延遲的過程中必然出現(xiàn)老代碼和新代碼混合的情況,這個時候?qū)τ脩粽埱蟮奶幚肀厝淮嬖诓淮_定性昨忆。
opcache.max_accelerated_files
這個選項用于控制內(nèi)存中最多可以緩存多少個PHP文件丁频。這個選項必須得設(shè)置得足夠大,大于你的項目中的所有PHP文件的總和邑贴。我的代碼庫大概有6000個PHP文件席里,所以我把這個值設(shè)置為一個素數(shù)7963(譯注:不知道這哥們?yōu)槭裁匆O(shè)置這個數(shù),7963也不是大于6000的最小素數(shù))拢驾。
你可以運行“find . -type f -print | grep php | wc -l”這個命令來快速計算你的代碼庫中的PHP文件數(shù)奖磁。
opcache.memory_consumption
這個選項的默認值為64MB,我把它設(shè)置為192MB繁疤,因為我的代碼很大署穗。你可以通過調(diào)用opcachegetstatus()來獲取opcache使用的內(nèi)存的總量,如果這個值很大嵌洼,你可以把這個選項設(shè)置得更大一些。
opcache.interned_strings_buffer
這是一個很有用的選項封恰,但是似乎完全沒有文檔說明麻养。PHP使用了一種叫做字符串駐留(string interning)的技術(shù)來改善性能。例如诺舔,如果你在代碼中使用了1000次字符串“foobar”鳖昌,在PHP內(nèi)部只會在第一使用這個字符串的時候分配一個不可變的內(nèi)存區(qū)域來存儲這個字符串,其他的999次使用都會直接指向這個內(nèi)存區(qū)域低飒。這個選項則會把這個特性提升一個層次——默認情況下這個不可變的內(nèi)存區(qū)域只會存在于單個php-fpm的進程中许昨,如果設(shè)置了這個選項,那么它將會在所有的php-fpm進程中共享褥赊。在比較大的應(yīng)用中糕档,這可以非常有效地節(jié)約內(nèi)存,提高應(yīng)用的性能拌喉。
這個選項的值是以兆字節(jié)(megabytes)作為單位速那,如果把它設(shè)置為16,則表示16MB尿背,默認是4MB端仰,這是一個比較低的值。
opcache.fast_shutdown
另外一個很有用但也沒有文檔說明的選項田藐。從字面上理解就是“允許更快速關(guān)閉”荔烧。它的作用是在單個請求結(jié)束時提供一種更快速的機制來調(diào)用代碼中的析構(gòu)器吱七,從而加快PHP的響應(yīng)速度和PHP進程資源的回收速度,這樣應(yīng)用程序可以更快速地響應(yīng)下一個請求鹤竭。把它設(shè)置為1就可以使用這個機制了踊餐。