問題背景
通過啟用Opcache的緩存優(yōu)化,將PHP代碼預(yù)編譯為Opcode緩存到共享內(nèi)存中供進(jìn)程反復(fù)調(diào)用,從而減少了重復(fù)從磁盤解析PHP代碼的時間消耗,顯著的提高了PHP性能,提升了業(yè)務(wù)性能的調(diào)用,但是也引發(fā)了一些問題,就是我們每次更新了相應(yīng)的PHP代碼后,web server 無法即時加載到更新后的代碼。
解決方案
(一)、設(shè)置Opcache腳本驗(yàn)證時間
可以通過更改 Opcache 以下兩個配置選項(xiàng)來調(diào)整代碼重載時間
opcache.revalidate_freq=0 檢查腳本時間戳是否有更新的周期,以秒為單位。(如果設(shè)置為 0 會導(dǎo)致針對每個請求, OPcache 都會檢查腳本更新)
opcache.validate_timestamps=0 如果啟用,那么 OPcache 會每隔 opcache.revalidate_freq 設(shè)定的秒數(shù) 檢查腳本是否更新。
PS:在實(shí)際生產(chǎn)環(huán)境中,為了盡可能達(dá)到最優(yōu)性能,盡量不開啟文件更新驗(yàn)證,因?yàn)槊看悟?yàn)證都會重新預(yù)編譯PHP代碼到共享內(nèi)存中。
(二)、重啟 | 重載 php-fpm 進(jìn)程
每次重啟或重啟 php-fpm 進(jìn)程便會重新解析PHP腳本文件,但是重啟 fpm 進(jìn)程可能會導(dǎo)致請求中斷,從而導(dǎo)致寫入臟數(shù)據(jù) 或者 造成事務(wù)回滾等一系列異常。
重載相對于重啟則平順很多,不會導(dǎo)致用戶請求直接中斷,相對來說風(fēng)險低很多,但是php-fpm 收到reload信號,便會向所有子進(jìn)程發(fā)送SIGGUIT信號,同時注冊一個定時器,在規(guī)定的時間之內(nèi)子進(jìn)程沒有退出,接著在發(fā)送SIGTERM信號,結(jié)束子進(jìn)程。如果在一秒之內(nèi)子進(jìn)程還是沒結(jié)束 直接發(fā)送SIGKILL 強(qiáng)制殺死。
重啟php-fpm
重載php-fpm
services php-fpm reload
或 kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
(三)、手動清理緩存
除了上面的兩種方式,還有更為穩(wěn)妥一點(diǎn)的緩存清理,我們可以通過opcache_reset()和opcache_invalidate() 函數(shù)來刷新Opcache緩存。
opcache_reset()
- 重置整個Opcode緩存,所有的PHP腳本將會被重新解析再預(yù)編譯為Opcode。
opcache_invalidate()
- 清除指定腳本緩存,可以傳遞兩個參數(shù),一個是刷新文件路徑,一個是force字段, 如果 force 沒有設(shè)置或者傳入的是 FALSE,那么只有當(dāng)腳本的修改時間 比對應(yīng)Opcode的時間更新時,腳本的緩存才會失效。
需要注意的是,當(dāng)PHP以PHP-FPM的方式運(yùn)行的時候,opcache的緩存是無法通過php命令進(jìn)行清除的,只能通過http或cgi到php-fpm進(jìn)程的方式來清除緩存,我們可以編寫一個對外接口,來達(dá)到清理緩存的目的。
相關(guān)實(shí)現(xiàn)如下(框架:laravel):
Route::any('cache-reset', function () {
//重置整個Opcode緩存
dd(opcache_reset());
});
Route::any('cache-update', function () {
//清除掉最近一次更新文件的緩存
exec('git diff --name-only HEAD~ HEAD', $output);
foreach ($output as $file) {
$path = base_path($file);
opcache_invalidate($path, true);
}
dd('刷新完成');
});
總結(jié)
通過上面的三種策略,可以實(shí)現(xiàn) Opcache 緩存更新的目的,但是在流量高峰期或者大流量的服務(wù)端,每次更新緩存都是一件非常損耗資源的事情,Opcache在重建緩存時,也不會禁止其他進(jìn)程讀取,因此就會造成反復(fù)新建緩存,因此想要達(dá)到最佳的性能調(diào)配:
- 最好不要在高峰期清理緩存
- 高峰期不要頻繁的更新代碼,清理緩存,會造成重復(fù)新建緩存
- 如果需要更新,可以嘗試削弱服務(wù)端權(quán)重,實(shí)現(xiàn)逐個更新的目的。
- 如果需要強(qiáng)制更新,盡量選擇手動清除緩存的方式,來重建Opcache緩存,使代價最小化。
以上就是解決PHP Opcache 緩存刷新、代碼重載出現(xiàn)無法更新代碼的問題的詳細(xì)內(nèi)容,更多關(guān)于PHP Opcache 緩存刷新、代碼重載的資料請關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:- 詳解PHP7開啟OPcache和Swoole性能的提升對比
- 如何使用OPCache提升PHP的性能
- PHP如何開啟Opcache功能提升程序處理效率
- php加速緩存器opcache,apc,xcache,eAccelerator原理與配置方法實(shí)例分析
- 啟用OPCache提高PHP程序性能的方法
- PHP解決高并發(fā)問題(opcache)