data-id="1190000004975909" data-licence="">
昨晚線上出故障,緊急處理切換容災後緩解了故障,解決故障後從容災切換回正式服務時發現PHP檔案更新無效,重啟FPM後才生效。下面記錄複盤追查的過程。
因為是PHP檔案更新不生效,所以馬上懷疑到opcache上面,到線上看了一眼php.ini,果然使用了opcache,並且活動訊號間隔時間時間設定為60秒。查看昨晚的日誌,更新不生效期間遠遠大於60秒,所以這個活動訊號間隔時間時間的問題可以PASS了,我們繼續。
線上上環境查看更新的檔案和日誌中的時間的時候,突然發現PHP檔案時間和日誌中的時間對應不上,馬上找OP確認,OP交待說這個檔案是復原mv回來的,所以檔案時間和我預期的不一致。我用stat命令看了一下,果然modify time相比access time早了一段時間,依據這點線索推測opcache依靠的是PHP檔案的modify time作為檔案被修改的檢測條件。線上下複現問題,填坑成功!
下面總結一下填坑過程中查的一些相關的知識點
載入opcache
在php.ini中增加opcache時需要使用zend_extension,而不是extension,不然會得到以下WARNING
PHP Warning: PHP Startup: Invalid library (appears to be a Zend Extension, try loading using zend_extension=opcache.so from php.ini) in Unknown on line 0
配置opcache
使用下列推薦設定來獲得較好的效能:
opcache.memory_copcache.interned_strings_buffer=8opcache.max_accelerated_files=4000opcache.revalidate_freq=60opcache.fast_shutdown=1opcache.enable_cli=1
本次涉及到的有兩個參數
revalidate_freq,預設2
檢查指令碼時間戳記是否有更新的周期,以秒為單位。 設定為 0 會導致針對每個請求, OPcache 都會檢查指令碼更新
validate_timestamps,預設1
如果啟用,那麼 OPcache 會每隔 opcache.revalidate_freq 設定的秒數 檢查指令碼是否更新。 如果禁用此選項,你必須使用 opcache_reset() 或者 opcache_invalidate() 函數來手動重設 OPcache,也可以 通過重啟 Web 服務器來使檔案系統更改生效。
系統命令和函數stat
access time 表示我們最後一次訪問檔案的時間
modify time 表示我們最後一次修改檔案的時間
change time 表示我們最後一次對檔案屬性改變的時間,包括許可權,大小,屬性等等
C/C++中也可以使用stat方法查詢檔案的這3個時間屬性,一般應用都會通過modify time判斷檔案是否更新,我們本次踩坑就是因為檔案是mv操作的,modity time沒有更新,所以opcache沒有更新。
以上就介紹了opcache的檢測檔案更新的小坑,包括了cache方面的內容,希望對PHP教程有興趣的朋友有所協助。