NAS讀取延時問題及NFS快取機制
業務場景:
- 前臺通過RPC呼叫後臺,在NAS指定路徑生成圖片
- 前臺直接到NAS盤中獲取該圖片,在瀏覽器中進行展示
問題:
前臺tomcat報出404錯誤,提示找不到該資源
問排查過程:
- 分別登入前後臺伺服器,進入上述圖片路徑,
ls 圖片名
檢查圖片是否存在。發現前後臺伺服器均能看到該圖片。 - 在後臺伺服器上使用
mv 圖片名 test
,將圖片改名為test。再次ls
檢查,發現後臺伺服器上原圖片已變為test,但前臺伺服器上任然只能看到原圖片,無法看到test。間隔50s再次檢查,發現前臺伺服器上原圖片也已變為test。 - 小結:在後臺伺服器上對NAS盤內檔案進行變更,無法被前臺伺服器立即捕獲到。
- 檢查磁碟載入配置
cat /etc/fstab
發現對應NAS盤載入配置為
XXX.XX.XXX.XX:/XXX_NAS_0001 /appnas nfs vers=3,rsize=1048576,wsize=1048576,hard,intr 0 0
man nfs
檢視/etc/fstab的說明文件,發現這樣一段話
ac / noac
Selects whether the client may cache file attributes. If neither option is specified (or if ac is specified), the client caches file attributes.
To improve performance, NFS clients cache file attributes. Every few seconds, an NFS client checks the server’s version of each file’s attributes for updates. Changes that occur on the server in those small intervals remain undetected until the client checks the server again. The noac option prevents clients from caching file attributes so that applications can more quickly detect file changes on the server.
In addition to preventing the client from caching file attributes, the noac option forces application writes to become synchronous so that local changes to a file become visible on the server immediately. That way, other clients can quickly detect recent writes when they check the file’s attributes.
Using the noac option provides greater cache coherence among NFS clients accessing the same files, but it extracts a significant performance penalty. As such, judicious use of file locking is encouraged instead. The DATA AND METADATA COHERENCE section contains a detailed discussion of these trade-offs.
大意是
- 預設使用 ac 選項,開啟快取。客戶端每間隔幾秒取檢查一次變更狀態,這樣就不能及時獲取到檔案更新狀態;
- 使用noac選項將會關閉快取,因此需要檢查檔案屬性的每個操作都被強制返回伺服器,這就使得客戶可以快速檢視到檔案更改;
- 啟用noac會導致效能下降,鼓勵使用檔案鎖來代替它。
臨時解決方案
在NAS盤掛載選項中新增 noac
使用root許可權修改 /etc/fatab, 新增 noac選項
XXX.XX.XXX.XX:/XXX_NAS_0001 /appnas nfs vers=3,rsize=1048576,wsize=1048576,hard,intr,noac 0 0
使用 umount/ mount
重新掛載NAS盤。測試後確認問題暫時解決。
問題剖析
1. NFS快取機制
(轉自https://www.ibm.com/developerworks/cn/linux/l-cn-nfs/index.html)
如上圖所示,NFS 檔案系統使用 read,writeback,dirty 和 commit 四個佇列,每個佇列的單元資料結構都是 nfs_page,每個 nfs_page 都有一個 page 變數指向頁快取記憶體。
- 讀方法 nfs_readpage 首先使用非同步方式讀取資料,如果非同步方式失效,才使用同步方式,nfs_readpage_async 所讀的資料都進入 read 佇列中。
- 寫方法 nfs_writepage 如果寫資料超過一頁(預設是 4096 位元組),使用非同步方式提交資料,否則使用同步方式。nfs_writepage_async 所寫的資料首先進入 writeback 佇列,如果資料發生更改,則進入 dirty 佇列,如果將更改的資料提交到 NFS 伺服器上,則進入 commit 佇列。這些佇列或者因為超時,或者因為單元數量多於最大值,將被釋放掉。
小結:讀取資料時先讀快取,若快取中沒有該資料,則採用同步方式讀取,所有操作都被強制返回伺服器。
2. 根據快取機制再次進行測試分析
測試前先在前後臺伺服器上掛載測試用的NAS盤,cd進入測試的NAS盤路徑。注意不要使用noac選項,此時預設為ac模式。
- 在後臺伺服器NAS路徑中建立檔案
dd if=/dev/zero of=test count=5 bs=1M
- 在前臺伺服器上檢視該檔案
ls test
,發現可以檢視到 - 快速在前臺伺服器上執行
ls test1
, 此時必然報沒有該檔案。再到後臺伺服器上執行mv test test1
,將test改為test1 - 快速再前臺伺服器上執行
ls test
及ls test1
, 發現可以讀到test, 但無法讀到test1。即讀的結果與第一次相同,與實際情況不符。
小結:對同一檔案,第一次讀取因為沒有快取(即非同步方式讀取失敗),故採用同步方式讀取(不讀快取),因此可以立即獲取到變更。若緊接著進行第二次讀取,因為此時存在快取,非同步方式可以讀取成功,故不會進行同步讀取。若在此過程中,在其它客戶端對檔案進行了操作,則變更無法被獲取到。直到 nfs_writepage 寫資料超過一頁並提交,客戶端檢查到版本發生變化時,才會進行更新。
3. 再次對業務場景進行分析
瞭解清楚快取邏輯後,再次詢問相關開發人員,對業務場景進行分析。最後得知:
該業務場景允許使用者在登入狀態下,連續重新整理頁面。每次重新整理都會重新向後臺發起請求,重新生成圖片(圖片名稱保持不變),前臺再重新到NAS中獲取並展示該圖片。
小結分析:後臺伺服器對NAS中同一檔案進行連續重新生成操作,同時在前臺伺服器上進行連續讀。這就意味著,在獲取到變更狀態之前,前臺伺服器讀到的都是快取。
但是這樣就帶來了一個新的問題:第一次讀取時,該檔案被載入到了快取中。後續就算快取中不是最新的檔案,也應當可以讀取到第一版快取中的檔案。那為什麼會出現“無法找到該資源”的情況呢?
再次回顧快取機制:
“nfs_writepage_async 所寫的資料首先進入 writeback 佇列,如果資料發生更改,則進入 dirty 佇列,如果將更改的資料提交到 NFS 伺服器上,則進入 commit 佇列。”
如果檔案已經刪除了,那後續的修改實際上沒有意義的,佇列也就失去了價值。此處猜測,對於刪除操作(REMOVE),會直接提交到NFS伺服器,並寫入到客戶端快取。以下進行測試驗證:
測試前依舊注意使用預設的ac模式,cd進入測試的NAS盤路徑。
- 在後臺伺服器NAS路徑中建立檔案
dd if=/dev/zero of=test count=5 bs=1M
- 在前臺伺服器上檢視該檔案
ls test
,發現可以檢視到 - 在後臺伺服器上連續執行
rm test
dd if=/dev/zero of=test count=5 bs=1M
- 迅速在在前臺伺服器上檢視該檔案
ls test
,發現報錯
ls: cannot access test: No such file or directory
如此一來就證實了以上的猜想。
最終解決方案
- 為了避免影響NAS效能,繼續使用預設的ac非同步模式
- 業務上避免對同一檔案的連續讀寫操作。具體的方式為:
- 對於連續重新生成同一檔案的場景:通過加時間戳等方式,每次生成不同的檔名,同時設定定時任務,定期清理,或在業務流程中增加刪除規則;
- 對於不同伺服器連續修改NAS內同一檔案的場景,增加檔案鎖機制。
參考文件:
- NFS 檔案系統原始碼剖析 https://www.ibm.com/developerworks/cn/linux/l-cn-nfs/index.html
- 建議的 NFS 掛載選項 https://docs.aws.amazon.com/zh_cn/efs/latest/ug/mounting-fs-nfs-mount-settings.html