OPcache經過opcode的緩存和優化,提供更快的PHP執行過程。
業務在php7環境運營時,爲了提高請求的性能,在PHP7環境中配置OPcache擴展。
業務在更新代碼後,訪問業務系統時提示沒法找到對應的文件或請求的內容仍是更新前的舊內容,
webserver重啓之後,請求訪問到的文件就都是最新的了,問題就貌似解決了。php
根據現象分析,代碼更新後請求找不到新增的文件,尤爲是還在請求已有文件更新前的內容,那麼可能跟緩存有關係,考慮到跟業務代碼邏輯無關,關閉opcache的配置問題就再也不出現,基本上能夠定位到問題出在opcache的配置上。web
cat /usr/local/php/etc/subconfig/opcache.inizend_extension=opcache.soopcache.enable=1opcache.revalidate_freq=0opcache.validate_timestamps=0opcache.max_accelerated_files=7963opcache.memory_consumption=192opcache.interned_strings_buffer=16opcache.fast_shutdown=1opcache.enable_cli=1
opcache.enable 啓用操做碼緩存,默認爲「1」
若是禁用此選項,則不會優化和緩存代碼。 在運行期使用 ini_set() 函數只能禁用 opcache.enable 設置,不能夠啓用此設置。 若是在腳本中嘗試啓用此設置項會產生警告。緩存
opcache.enable_cli 僅針對 CLI 版本的 PHP 啓用操做碼緩存。bash
一般被用來測試和調試。服務器
opcache.revalidate_freq=0 檢查腳本時間戳是否有更新的週期,以秒爲單位。php7
設置爲 0 會致使針對每一個請求, OPcache 都會檢查腳本更新。ide
opcache.validate_timestamps=0 若是啓用,那麼 OPcache 會每隔 opcache.revalidate_freq 設定的秒數 檢查腳本是否更新。函數
若是禁用此選項,你必須使用 opcache_reset() 或者 opcache_invalidate() 函數來手動重置 OPcache,也能夠 經過重啓 Web 服務器來使文件系統更改生效。php-fpm
最初的配置是:
opcache.revalidate_freq=60,opcache.validate_timestamps=1
即每60秒檢測一次更新字節碼緩存,業務代碼更新後可能須要60秒之後才能訪問到最新的內容,也就出現了最初訪問不到新增的內容。oop
php代碼的更新方式有兩種,一種是覆蓋webserver配置的目錄下的文件來更新,一種是每次都部署一個全量包目錄,而後軟連接到webserver指定的目錄。
第一種覆蓋更新的方式,若是使用在過時時間後自動清理opcache緩存內容的話,更新操做若是有延遲,就會出現新舊代碼文件混合在一塊兒的狀況。
第二種全量包目錄發佈後,軟連接到webserver指定路徑的方式,雖然不會存在新舊文件混合的問題,可是在未自動清理時,即使webserver已經連接到webserver對應目錄,業務訪問的仍是舊文件。
目前使用rsync同步目錄文件的方式是咱們更新代碼的主要方式,最初使用每60s定時清理opcache的緩存文件,在60s內更新的文件不會生效,就致使了業務反饋代碼更新後訪問不到的問題。
使用定時更新代碼緩存的問題,還有更新文件較多時,代碼文件發佈的過程當中緩存發生更新,將會有60s新舊文件的緩存混合存在的問題。
根據相關研究人員推薦,若是採用覆蓋更新代碼文件時,更新操做完畢後,手動清理緩存比較合適。
opcache.validate_timestamps=0
即,將oopcache.validate_timestamps設置爲0。
配置了opcache.validate_timestamps值爲0,必須手動清空Zend OPcache緩存的字節碼,才能訪問到最新的文件內容。適合在生產環境中設置爲0,但在開發環境會帶來不便,能夠在開發環境中這樣配置啓用自動驗證緩存功能:
opcache.validate_timestamps=1
opcache.revalidate_freq=0
除了重啓php-fpm的進程能夠清理opcache緩存外,
手動清理緩存涉及到的opcache函數主要爲:opcache_reset()和opcache_invalidate() 。
boolean opcache_reset ( void ) 該函數將重置整個字節碼緩存。 在調用 opcache_reset() 以後,全部的腳本將會從新載入而且在下次被點擊的時候從新解析。
須要注意的是,當PHP以PHP-FPM的方式運行的時候,opcache的緩存是沒法經過php命令進行清除的,只能經過http或cgi到php-fpm進程的方式來清除緩存。
In some (most?) systems, PHP's CLI has a separate opcode cache to the one used by the web server , or PHP-FPM process,which means running opcache_reset() in the CLI, won't reset the webserver/fpm opcode cache, and vice-versa.
曲線救國,使用命令行清理php-fpm的opcache緩存:
#!/bin/bashcgi-fcgi -v > /dev/null 2>&1|| yum --enablerepo=epel install fcgi -y > /dev/null 2>&1echo '<?php opcache_reset(); echo "ok\n";' > /tmp/php-fpm-opcache-reset.php; SCRIPT_FILENAME=/tmp/php-fpm-opcache-reset.php \ REQUEST_METHOD=GET \ cgi-fcgi -bind -connect 127.0.0.1:9000; rm -f /tmp/php-fpm-opcache-reset.php;
opcache_invalidate 廢除指定腳本緩存
boolean opcache_invalidate ( string $script [, boolean $force = FALSE ] ) 該函數的做用是使得指定腳本的字節碼緩存失效。 若是 force 沒有設置或者傳入的是 FALSE,那麼只有當腳本的修改時間 比對應字節碼的時間更新,腳本的緩存纔會失效。 參數 script 緩存須要被做廢對應的腳本路徑 force 若是該參數設置爲TRUE,那麼無論是否必要,該腳本的緩存都將被廢除。
opcache_invalidate能夠針對單個或幾個腳本進行來清理緩存。
總結
若是代碼發佈是全量發佈,切換軟連接的方式,能夠設置opcache.validate_timestamps=1和opcache.validate_timestamps=1來定時自動更新緩存。若是代碼發佈是覆蓋更新舊目錄,則能夠重啓php-fpm及在腳本中或代碼文件中使用opcache_reset函數來清理全部緩存。若是能夠獲取到更新的代碼文件列表,則可使用opcache_invalidate函數來清理代碼,同時也能夠避免影響到其餘業務的緩存。