我有一台運行 Apache 2.4.6 的 CentOS 7 伺服器,帶有 Event MPM 和 php-fpm 版本 5.6.10(來自 REMI 儲存庫)。以下是向虛擬主機內的 php-fpm 發送請求的相關 Apache 配置(這是該伺服器上唯一的網站):
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
這是相關的 php-fpm 池配置:
listen = /var/run/php-fpm/www.sock
listen.owner = apache
listen.group = apache
pm = static
pm.max_children = 50
pm.max_requests = 0
這是 php-opcache 配置(預設安裝配置):
zend_extension=opcache.so
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
opcache.blacklist_filename=/etc/php.d/opcache*.blacklist
我的問題:每當我安裝並啟用 php-opcache 時,錯誤日誌中就會開始出現以下錯誤:
[Thu Jun 18 08:10:58.499871 2015] [mpm_event:debug] [pid 16546:tid 139798115227392] event.c(986): (104)Connection reset by peer: [client 157.55.39.233:15962] AH00470: network write failure in core output filter
[Thu Jun 18 08:10:58.527424 2015] [mpm_event:debug] [pid 16546:tid 139797922195200] event.c(986): (103)Software caused connection abort: [client 157.55.39.233:15990] AH00470: network write failure in core output filter
如果我刪除 php-opcache,錯誤就會消失。每當發生這種情況時,使用者都會在前端報告 502 服務不可用錯誤。
我實際上花了至少 6 個小時嘗試 Google 並找到解決方案。有人說 opcache 的fastshutdown
選項有問題,但它在預設配置中被禁用。我將 php-fpm 進程管理方法變更為靜態,不進行回收(max_requests=0),但這也沒有改變任何內容。我還嘗試使用 Apache 的 TCP 代理方法(而不是套接字),這也沒有影響。
我不確定這是否相關,但無論是否安裝 php-opcache,我都會在錯誤日誌中報告以下錯誤(但頻率要小得多,<所有流量的 0.5%,這可能是一個單獨的問題):
[Thu Jun 18 08:32:37.223430 2015] [proxy_fcgi:error] [pid 19187:tid 140598765840128] [client 37.46.115.238:55624] AH01068: Got bogus version 10, referer: ...
[Thu Jun 18 08:32:37.223462 2015] [proxy_fcgi:error] [pid 19187:tid 140598765840128] (22)Invalid argument: [client 37.46.115.238:55624] AH01075: Error dispatching request to :, referer: ...
這個問題非常類似這個,儘管那個人正在使用 ProxyPassMatch 和 TCP 方法,但我不是(因為繞過 .htaccess)。
有人有我尚未提到的想法嗎?
答案1
當我在我們的環境中看到類似問題時,這似乎是由於 OpCache(預設)在共享託管環境上的所有用戶之間共享單一快取的方式造成的。 A錯誤已提交(你可以而且應該去投票讓維護者知道這對你的用例有多重要)儘管沒有承諾提供修復。
TL;DR:預設情況下,當 OpCache 啟用時,用於儲存已編譯字節碼的快取在所有使用者之間共用。在多個網站/使用者之間共用託管的環境中,這可能會導致網站從另一個網站獲取 php 腳本的快取輸出,或者如果啟用了特定的安全性設置,甚至會產生錯誤。
如果您打算將 PHP-FPM 與 PHP 5.5+ 的內建 opcache 一起使用,請在實際執行之前閱讀下面的部落格文章。事實證明,操作碼快取可以被伺服器上的任何使用者讀取。這意味著,如果有 10 個單獨的用戶,擁有自己的虛擬主機和目錄,並且您為每個用戶配置一個 PHP-FPM 池,則每個用戶仍然可以看到快取的腳本及其位置。由於他們具有對快取的讀取存取權限,因此他們可能會查看所有這些資料。
這顯然是一個巨大的安全問題,即使沒有人利用這一點,在生成頁面時仍有可能由錯誤的用戶讀取腳本,因此如果存在多個索引,網站可能會顯示錯誤的資料/資訊快取中的.php 腳本。
雖然官方尚未發布修復程序,但如果您使用 cPanel,這個 wiki 有一個記錄的方法來配置要在每個使用者的基礎上建立和保護的 php-fpm 池如果您按照以下說明以及重要筆記在這個答案的底部,您應該能夠獲得您想要的功能,而不會出現任何錯誤
該文章還記錄瞭如何在每個站點/每個用戶的基礎上手動配置它(儘管我敢打賭,如果您託管很多站點,這可能會變得乏味)。如果您不使用 cPanel,您可能需要修改腳本來指定您的個人路徑和使用者名,而不是 cPanel 的設定引擎所使用的變數。
重要筆記
在測試和其他研究過程中我遇到了這篇文章提供了一些說明這可能與您的具體情況相關:
- 您需要確保該
opcache.use_cwd
參數設定true
為您的應用程式的 OpCache 配置 -false
預設情況下將其設為預設值,如果您在系統上託管多個 PHP 應用程序,則將其保留為預設值可能會導致衝突:
首先,可能在每個典型專案中,您都必須確保 opcache.use_cwd 選項設為 true。啟用此設定表示 OpCache 引擎將查看完整檔案路徑以區分同名檔案。將其設為 false 將導致具有相同基本名稱的檔案之間發生衝突。
- 如果您正在運行由 Zend Framework 或其他使用註釋的類似框架提供支援的應用程序,您還需要確保
opcache.load_comments
和opcache.save_comments
指令設定為true
.您應該仔細檢查您的應用程式/框架文件中的此建議,因為大多數應用程式/框架文件現在已經更新了他們的文檔,其中包含有關在其係統中正確使用 OpCache 的具體說明:
在使用註解的工具和框架中還有一個很重要的設定。如果您使用 Doctrine、Zend Framework 2 或 PHP Unit,請記得將 opcache.load_comments 和 opcache.save_comments 設為 true。因此,文件中的文件註解也將包含在 OpCache 產生的預編譯程式碼中。此設定將允許您在沒有任何中斷的情況下使用註解。
如果您的專案基於特定框架或 Web 應用程序,那麼檢查文件以獲取有關 OpCache 配置的任何指南總是一個好主意
重要筆記
希望這對您有所幫助 - 如果您使用 cPanel,請發表評論,讓我們知道您如何處理這部分配置! 另請參閱此問題和相關評論。