php session_write_close 警告

php session_write_close 警告

session_write_close我們所有的錯誤都會記錄到 NewRelic 中,並且我們總是在錯誤日誌中看到一些警告。然而,錯誤率增加了,現在已經淹沒了我們的 24 小時日誌。

我們的伺服器人口眾多,有許多用戶同時登入。大多數用戶不會看到這些session_write_close警告。有些確實如此,這使得我們幾乎不可能找到原因並解決它。

這是完整的錯誤訊息:

Error message
E_WARNING: session_write_close(): Failed to write session data (files).    
Please verify that the current setting of session.save_path is correct        
(/opt/php55/var/lib/php/session-nginx)

所以我做了檢查,看看目錄中有多少文件9431以及權限是什麼-rw------- 1 nginx nginx

我沒有發現我的配置、檔案權限等有任何問題。

我們別無選擇。我可以做什麼來解決這個問題?目前影響不到 1% 的用戶,我們只想將影響率保持在盡可能低的水平。

這是我的 php.ini 配置列表。

Directive   Local Value Master Value
session.auto_start  Off Off
session.cache_expire    180 180
session.cache_limiter   nocache nocache
session.cookie_domain   no value    no value
session.cookie_httponly Off Off
session.cookie_lifetime 0   0
session.cookie_path /   /
session.cookie_secure   Off Off
session.entropy_file    /dev/urandom    /dev/urandom
session.entropy_length  32  32
session.gc_divisor  1000    1000
session.gc_maxlifetime  1440    1440
session.gc_probability  1   1
session.hash_bits_per_character 5   5
session.hash_function   0   0
session.name    PHPSESSID   PHPSESSID
session.referer_check   no value    no value
session.save_handler    files   files
session.save_path   /opt/php55/var/lib/php/session-nginx    /opt/php55/var/lib/php/session-nginx
session.serialize_handler   php php
session.upload_progress.cleanup On  On
session.upload_progress.enabled On  On
session.upload_progress.freq    1%  1%
session.upload_progress.min_freq    1   1
session.upload_progress.name    PHP_SESSION_UPLOAD_PROGRESS PHP_SESSION_UPLOAD_PROGRESS
session.upload_progress.prefix  upload_progress_    upload_progress_
session.use_cookies On  On
session.use_only_cookies    On  On
session.use_strict_mode Off Off
session.use_trans_sid   0   0

一些伺服器統計: CentOS 6.6 PHP 5.5.28 Nginx 1.6.2 歡迎任何幫助!

答案1

對於高負載的伺服器,我會使用memcached(甚至可能redis?)進行會話儲存。因此,如果我處於您的情況,我可能會出於自身原因而進行設置,然後看看問題是否會偶然消失。

我也不會使用 php 的會話垃圾收集,它會掛起網路請求作業的垃圾收集。我會設定自己的作業來處理這個問題,要嘛從 cron 運行,要嘛從某個作業排隊系統運行。

除了 php 的會話垃圾回收之外,您是否已經擁有任何類型的會話清理系統?

這種情況發生的機率是 0.1%,這與您的設定相符嗎session.gc_divisor

您的 php 進程是否以 nginx 使用者身分執行?根據設定進行清理的是 php 而不是 nginx session.gc_*。如果 php 作為 nginx 運行,那麼在存取 php 會話檔案方面是好的,但在與 nginx 伺服器共用使用者 ID 方面可能不好。

您可能需要該會話目錄的執行權限,以便垃圾收集器可以查看需要清理的內容。

session.save_path如果您沒有針對您的應用程式進行特定設置,我也會擔心。這意味著,如果您有多個應用程式共用相同會話目錄,那麼當垃圾收集運行時,到期時間最短的應用程式將獲勝,從而清除其他應用程式的會話。

答案2

我從你的問題中得到的明顯觀察是,你在嘗試將文件保存到 /opt/php55/var/lib/php/session-nginx 時遇到了太多瓶頸。因此,您的解決方案是緩解瓶頸,首先診斷出具體出了什麼問題。
假設它正在競速寫入磁碟,並且錯誤是它放棄的標誌,我預計 dmesg 錯誤會顯示寫入磁碟的問題。如果是這種情況,您可以寫入記憶體或其他相當於更快「磁碟」的解決方案。
mc0e 提到 memcached 而不是使用 save_handle=files,這是一個不錯的選擇。 memcached 的替代方案可能是使用 tmpfs,它本質上將會話同樣放入記憶體中(因此寫入時間很快),但不需要新的應用程式。
我還想問 /opt/php55/var/lib/php/session-nginx 是什麼類型的檔案系統?對於基本上是 mktmp 類型的操作,您不需要 ext3/4 的所有複雜日誌記錄。您可能想要在 /tmp 中建立一個資料夾並將其符號連結到位,以確保減少建立檔案的開銷。
硬體設定是怎樣的?如果它是沒有快取的單一磁碟,並且在效能達到峰值時,您應該會在 dmesg 中看到問題。我在所有伺服器中都使用了 AMCC Raid 控制器和 Raid-1。如果是Raid-1(鏡像),則讀取速度會很快,但寫入速度將取決於raid 的實現程度(我知道AMCC 可以在Raid-1 中跨磁碟進行寫入,但並非所有RAID-1實現這樣做,我知道軟體突襲不會)。出於這個原因,我的老老闆非常信賴 Raid-5,只要它是真正的硬體 raid(如果不是,RAID-5 在 CPU 上可能會很昂貴),這將極大地加快您的磁碟吞吐量。另一種選擇是固態磁碟,但實際上,如果您要走這條路,我建議使用 memcached 或 tmpfs,因為更多記憶體始終是一個好的計劃(相對於任何其他新硬體)。

最簡單的解決方案是建立 /tmp/session-nginx 和符號連結或將 /opt/php55/var/lib/php/session-nginx 掛載到 /tmp/session-nginx/

答案3

部分問題是很難追蹤這些類型的錯誤,那麼我可能建議在 try/catch 區塊中明確關閉程式碼上的會話。處理異常,睡眠並重試。

問題的另一部分描述了一個本質上隨機的寫入錯誤。這不是我所期望的不正確的權限。我懷疑你打開的文件太多。

我會調整一些配置來看看會發生什麼:

  1. 增加開啟檔案的限制您可能在作業系統的某些部分設定了一些下限。例如,我的筆記本支援數十萬個開啟文件,但同一用戶只能開啟 4000 個文件。

  2. 將 maxrequestperchilds 降低到 1000這將使每個 http 伺服器在服務 1000 個客戶端後重新啟動。

  3. 減少最大客戶端數增加 ListenBacklog。這是非常非常違反直覺的,但是如果您將 MaxClients/Servers 設定得太高,許多進程將爭奪伺服器中的資源並導致瓶頸。這在很大程度上取決於您所面臨的瓶頸類型。我的是資料庫伺服器。

相關內容