記一次內存變更引起的NFS故障
最近由于一些原因,做服務器資源調整,其中一臺服務器是做NFS服務,通過NFS掛載到其他幾臺服務器做共享,服務器內存從8G調整到了4G,其他不變
降配完成后,重啟服務器,看著一切正常,就沒管了
第二天DBA和我說數(shù)據(jù)備份沒寫入,登錄服務器查看,df -H命令卡住,憑經(jīng)驗,NFS掛了
登錄NFS服務器,查看NFS服務正常,查看message日志,發(fā)現(xiàn)大量關于RPC的日志
日志報錯,分片太大
為什么之前是好的,降內存后,就出現(xiàn)分片太大,無法處理的情況?
通過查找NFS源碼,發(fā)現(xiàn)如下一段:
- /*
- * To change the maximum rsize and wsize supported by the NFS client, adjust
- * NFS_MAX_FILE_IO_SIZE. 64KB is a typical maximum, but some servers can
- * support a megabyte or more. The default is left at 4096 bytes, which is
- * reasonable for NFS over UDP.
- */
- #define NFS_MAX_FILE_IO_SIZE (1048576U)
- #define NFS_DEF_FILE_IO_SIZE (4096U)
- #define NFS_MIN_FILE_IO_SIZE (1024U)
原來,NFS服務器在決定默認的最大讀寫塊大小時會考慮內存的占用情況,每個NFS內核線程最多只使用1/4096的物理內存大小,對于UDP來說,由于一個UDP包最大才64KB,因此使用UDP協(xié)議的NFS讀寫塊大小最大不超過48KB,而kernel中則直接限制為32KB了,而使用TCP協(xié)議的NFS由于沒有這個限制,允許更大的讀寫塊大小,單Linux kernel還是將其限制為1MB了,對于物理內存超過4GB的機器才使用最大的1MB讀寫塊大小,而記錄這個大小的文件為/proc/fs/nfsd/max_block_size
查看服務端該值大小為512KB
因為讀寫對應的是rsize和wsize,是客戶端和服務端協(xié)商決定的,所以通過命令
- cat /proc/mounts |grep rsize
查看此時客戶端的rsize和wsize
客戶端rsize和wsize都是1048567,正好是1M
而上面我們看到服務端是512K,所以兩邊目前是不協(xié)商的
猜測原因如下:NFS服務器內存降配前,原先8G內存,大于4G,所以max_block_size應該是最大值1M,也就是1048567,和客戶端協(xié)商后,兩邊都定位默認的1048567
當NFS服務器降配到4G后,由于內存保護及計算,NFS服務端max_block_size降為512KB,也就是524288,此時服務端和客戶端不匹配
而客戶端沒有重新連接服務端,導致未協(xié)商,所以客戶端分片的數(shù)據(jù)包,遠大于服務端能處理的數(shù)據(jù)包,也就出現(xiàn)了message中的報錯,RPC數(shù)據(jù)分片太大
知道問題原因,就開始解決,解決方法分兩種
- 客戶端重新掛載
- 服務端修改max_block_size
我這里選擇了第二種方案,直接修改服務端max_block_size,因為是/proc數(shù)據(jù),nfs在啟動占用,所以需要停掉nfs修改
- systemctl stop nfs
- # 修改max_block_size
- echo 1048567 > /proc/fs/nfsd/max_block_size
修改完成后,重新啟動NFS
- systemctl start nfs
查看message,日志正常,查看客戶端,df -H可以正??吹綊燧d目錄,進入掛載目錄正常
這里我為什么不用第一種方案?
因為此時NFS服務端是掛掉的,客戶端無法卸載,卸載會提示占用無法卸載,能卸載的方式是兩邊都重啟,重新后重新進行協(xié)商,我不愿意重啟客戶端服務器,所以選擇第二種方式
完成后查看nfs傳輸
可以看到,傳輸正常,另外可以看到NFS此時是TCP協(xié)議的,也就驗證了TCP協(xié)議傳輸時,Linux內核最大限制1M塊大小了
本文轉載自微信公眾號「運維研習社」,可以通過以下二維碼關注。轉載本文請聯(lián)系運維研習社公眾號。