一台配置強悍的檔案伺服器(64 GB 記憶體、2 顆 12 核 CPU、外掛存儲),系統負載卻每隔一段時間週期性飆升至 40-50,而 top/vmstat/iostat/ifstat/sar 顯示 CPU、記憶體、磁碟、網路均極度閒置。本文複盤這一經典「負載高但資源閒」案例,揭示 NFS 服務執行緒數不足導致請求排隊、進程進入不可中斷睡眠 (D 狀態) 推高負載的根因,並給出生產級調優參數與驗證方法。
top 顯示 %idle > 90%、%iowait < 5%、記憶體充裕、無 Swap、網路流量平穩。ps aux | grep nfsd 僅見 8 條 nfsd 執行緒(預設值)。nfsd 執行緒池固定為 8 條,無法並行處理百人並發。load average 統計包含 R (Running) + D (Uninterruptible Sleep) 進程數。load average 飆升,但 CPU 實際閒置。# 觀察 D 狀態進程數
ps aux | awk '$8 ~ /D/ {count++} END {print "D state processes:", count}'
# 或
watch -n 1 'ps aux | grep -c " D "'
負載高峰期將觀測到數十上百個 D 狀態 nfsd 相關進程(實為客戶端進程在 nfs_wait_request 等待)。
# RHEL/CentOS 7/8
vim /etc/sysconfig/nfs
# 修改或新增
RPCNFSDCOUNT=160 # 建議:CPU 核心數 × 6-8,此處 24 核 × 6 ≈ 160
# Debian/Ubuntu
vim /etc/default/nfs-kernel-server
RPCNFSDCOUNT=160
systemctl restart nfs-server
# 或
systemctl restart nfs-kernel-server
# 驗證
ps aux | grep -c nfsd
# 應見 ~160 條 nfsd 執行緒
load average 長期維持在 2-5 區間(正常並發水平)。ps aux | grep D 僅見零星核心執行緒。nfsd 執行緒記憶體佔用極低(每條 ~KB 級),160 條總佔用 < 10 MB,CPU 佔用近乎為零(多為睡眠等待請求)。| 參數 | 建議值 | 說明 |
|---|---|---|
RPCNFSDCOUNT | 核心數 × 6-8 (如 160) | NFSD 執行緒池大小,核心調優點 |
RPCMOUNTDOPTS | --manage-gids -p 892 | 支援補充群組、固定埠便於防火牆 |
RPCSVCGSSDOPTS | -p 875 | Kerberos 固定埠 |
| 客戶端掛載選項 | rw,hard,intr,noatime,rsize=1048576,wsize=1048576,tcp,vers=4.2 | 大塊傳輸、TCP、NFSv4.2、硬掛載+可中斷 |
| 服務端匯出選項 | rw,sync,no_root_squash,no_subtree_check,fsid=0 | 同步寫入、根權限映射、禁用子樹檢查 |
load average 定義為「可運行佇列平均長度」,Linux 將 D 狀態 (TASK_UNINTERRUPTIBLE) 進程計入可運行佇列(因為它們佔用資源且不可殺死)。傳統認知「負載高 = CPU 壓力大」在這裡失效。正確判讀:
load 高 + %idle 高 + %iowait 低 → 大量 D 狀態 → 等待外部資源 (NFS/磁碟/鎖/網路)。load 高 + %user/%sys 高 → 真 CPU 瓶頸。load 高 + %iowait 高 → 磁碟/存儲子系統瓶頸。#!/bin/bash
# check_nfsd_threads.sh
EXPECTED=160
ACTUAL=$(ps aux | grep -c '\[nfsd\]')
LOAD1=$(uptime | awk -F'load average: ' '{print $2}' | awk -F', ' '{print $1}')
D_COUNT=$(ps aux | awk '$8 ~ /^D/ {c++} END {print c+0}')
echo "=== NFSd Thread Health Check ==="
echo "Expected threads: $EXPECTED"
echo "Actual threads: $ACTUAL"
echo "Load 1min: $LOAD1"
echo "D-state processes: $D_COUNT"
if [ $ACTUAL -lt $EXPECTED ]; then
echo "⚠️ WARNING: nfsd threads below expected!"
exit 1
elif [ $D_COUNT -gt 50 ]; then
echo "⚠️ WARNING: High D-state count, possible NFS congestion!"
exit 1
else
echo "✅ OK"
exit 0
fi
此案例深刻說明:服務層配置往往比硬體資源更決定效能上限。將 NFS 執行緒數納入基線配置標準、自動化巡檢與變更管理,避免「配置強但參數弱」的低級錯誤重演。