今天,我們來(lái)討論一下 PHP Opcache Bug 的問(wèn)題。 Opcache 是 PHP 5.5 版本中引進(jìn)的一個(gè)緩存擴(kuò)展,可以顯著提高 PHP 代碼的運(yùn)行速度。然而,最近一段時(shí)間發(fā)現(xiàn)了一些 PHP Opcache Bug 的問(wèn)題,這就使得 Opcache 失去了一些其本來(lái)能夠提供的優(yōu)勢(shì)。讓我們一步步來(lái)了解一下這個(gè) Bug 的本質(zhì)。
簡(jiǎn)單來(lái)說(shuō),由于一個(gè)叫做“canonicalization”的步驟的缺陷,Opcache 在緩存 PHP 代碼后無(wú)法正確地處理常量,導(dǎo)致緩存后的代碼出錯(cuò)。例如,我們有如下代碼:
const TEST = "test"; echo TEST;這段代碼可以正常運(yùn)行,輸出的結(jié)果是“test”。 然而,如果通過(guò) Opcache 緩存這段代碼,再開(kāi)啟緩存時(shí)運(yùn)行這段代碼,結(jié)果會(huì)不同:
const TEST = "test"; echo TESt; // 注意:這里拼寫大小寫不一致 // 輸出結(jié)果是: // Notice: Use of undefined constant TESt - assumed 'TESt' in ... // TESt從上面的結(jié)果可以看出,原本應(yīng)該輸出“test”的結(jié)果,因?yàn)槠磳戝e(cuò)誤,卻輸出了“TESt”。這就是 PHP Opcache Bug 造成的問(wèn)題。 此外,該 Bug 還會(huì)對(duì)一些框架或類庫(kù)造成影響。例如:
class Test { public static function foo() { return "bar"; } } echo Test::foo();這段代碼同樣可以正常運(yùn)行,輸出結(jié)果是“bar”。 但是,如果通過(guò) Opcache 緩存這段代碼,同時(shí)運(yùn)行時(shí)使用另一個(gè)類的同名方法,比如這樣:
class Test2 { public static function foo() { return "baz"; } } echo Test2::foo();這時(shí),使用 Test::foo() 方法將輸出“baz”,而非正常結(jié)果“bar”。同樣,這也是 PHP Opcache Bug 造成的問(wèn)題。 如何避免這個(gè) Bug 的影響呢?目前,最好的解決方案是在 Opcache 的配置中增加 opcache.consistency_checks = 0 的設(shè)置。這樣,Opcache 就不會(huì)檢查 PHP 代碼中的這個(gè)“canonicalization”的步驟,從而避免了這個(gè) Bug 的影響。 當(dāng)然,由于這個(gè)問(wèn)題在 PHP 中已經(jīng)被廣泛討論,因此預(yù)計(jì)不久之后就會(huì)有更好的解決方案出現(xiàn)。 總之,PHP Opcache Bug 的問(wèn)題可能會(huì)影響大量 PHP 代碼,因此我們有必要要認(rèn)識(shí)到這個(gè)問(wèn)題的存在,并采取措施進(jìn)行避免。希望這篇文章能對(duì)大家有所幫助。