1. 程式人生 > 程式設計 >解決PHP Opcache 快取重新整理、程式碼重載出現無法更新程式碼的問題

解決PHP Opcache 快取重新整理、程式碼重載出現無法更新程式碼的問題

問題背景

通過啟用Opcache的快取優化,將PHP程式碼預編譯為Opcode快取到共享記憶體中供程序反覆呼叫,從而減少了重複從磁碟解析PHP程式碼的時間消耗,顯著的提高了PHP效能,提升了業務效能的呼叫,但是也引發了一些問題,就是我們每次更新了相應的PHP程式碼後,web server 無法即時載入到更新後的程式碼。

解決方案

(一)、設定Opcache指令碼驗證時間

可以通過更改 Opcache 以下兩個配置選項來調整程式碼過載時間

opcache.revalidate_freq=0 檢查指令碼時間戳是否有更新的週期,以秒為單位。(如果設定為 0 會導致針對每個請求, OPcache 都會檢查指令碼更新)

opcache.validate_timestamps=0 如果啟用,那麼 OPcache 會每隔 opcache.revalidate_freq 設定的秒數 檢查指令碼是否更新。

PS:在實際生產環境中,為了儘可能達到最優效能,儘量不開啟檔案更新驗證,因為每次驗證都會重新預編譯PHP程式碼到共享記憶體中。

(二)、重啟 | 過載 php-fpm 程序

每次重啟或重啟 php-fpm 程序便會重新解析PHP指令碼檔案,但是重啟 fpm 程序可能會導致請求中斷,從而導致寫入髒資料 或者 造成事務回滾等一系列異常。

過載相對於重啟則平順很多,不會導致使用者請求直接中斷,相對來說風險低很多,但是php-fpm 收到reload訊號,便會向所有子程序傳送SIGGUIT訊號,同時註冊一個定時器,在規定的時間之內子程序沒有退出,接著在傳送SIGTERM訊號,結束子程序。如果在一秒之內子程序還是沒結束 直接傳送SIGKILL 強制殺死。

重啟php-fpm

service php-fpm restart

過載php-fpm

services php-fpm reload

或 kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

(三)、手動清理快取

除了上面的兩種方式,還有更為穩妥一點的快取清理,我們可以通過opcache_reset()和opcache_invalidate() 函式來重新整理Opcache快取。

opcache_reset() - 重置整個Opcode快取,所有的PHP指令碼將會被重新解析再預編譯為Opcode。

opcache_invalidate()

- 清除指定指令碼快取,可以傳遞兩個引數,一個是重新整理檔案路徑,一個是force欄位,如果 force 沒有設定或者傳入的是 FALSE,那麼只有當指令碼的修改時間 比對應Opcode的時間更新時,指令碼的快取才會失效。

需要注意的是,當PHP以PHP-FPM的方式執行的時候,opcache的快取是無法通過php命令進行清除的,只能通過http或cgi到php-fpm程序的方式來清除快取,我們可以編寫一個對外介面,來達到清理快取的目的。

相關實現如下(框架: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('重新整理完成');
});

總結

通過上面的三種策略,可以實現 Opcache 快取更新的目的,但是在流量高峰期或者大流量的服務端,每次更新快取都是一件非常損耗資源的事情,Opcache在重建快取時,也不會禁止其他程序讀取,因此就會造成反覆新建快取,因此想要達到最佳的效能調配:

  • 最好不要在高峰期清理快取
  • 高峰期不要頻繁的更新程式碼,清理快取,會造成重複新建快取
  • 如果需要更新,可以嘗試削弱服務端權重,實現逐個更新的目的。
  • 如果需要強制更新,儘量選擇手動清除快取的方式,來重建Opcache快取,使代價最小化。

以上就是解決PHP Opcache 快取重新整理、程式碼重載出現無法更新程式碼的問題的詳細內容,更多關於PHP Opcache 快取重新整理、程式碼過載的資料請關注我們其它相關文章!