全部產品
Search
文件中心

Alibaba Cloud Linux:Alibaba Cloud Linux 3系統的NFS檔案系統讀取檔案效能不符合預期,如何處理?

更新時間:Jul 17, 2024

在NFS(Network File System)檔案系統中通過read、copy_file_range等系統調用讀取檔案時,與同情境下的Alibaba Cloud Linux 2相比,可能會存在明顯的效能退化情況。本文介紹在Alibaba Cloud Linux 3系統的ECS執行個體中,在NFS檔案系統下讀取檔案時效能不符合預期的問題原因及解決方案。

問題描述

問題表現

在Alibaba Cloud Linux 3系統的NFS檔案系統中讀取檔案時效能不符合預期,典型表現如下:

  • 使用read、copy_file_range等系統調用從NFS檔案系統中讀取大檔案時,耗時較久。

  • 使用dd命令從NFS掛載點的檔案中讀取資料時,Alibaba Cloud Linux 3比Alibaba Cloud Linux 2用時多。例如:

    dd if=<nfs_mntpoint>/<testfile> of=/dev/null bs=1M
    說明

    該樣本命令表示從NFS掛載點的testfile檔案中讀取資料,並將其發送到/dev/null裝置中。運行完畢後,dd 會輸出一些資訊,包括讀取的總位元組數以及操作耗費的時間,用來計算讀取資料的速率,可以評估NFS檔案系統的效能表現。

影響範圍

該問題主要在以下ECS執行個體中存在:

  • 鏡像:aliyun_3_x64_20G_alibase_20210415.vhd及之後的所有鏡像版本。

  • 核心:5.10.23-4.al8.x86_64及之後的所有核心版本。

  • 檔案系統:掛載NFS檔案系統,讀取位於掛載點目錄下的檔案。

問題原因

在上遊Linux核心中,read_ahead_kb表示塊裝置的預讀視窗大小的參數。預讀(read-ahead)是一個效能最佳化技術,它允許系統預測接下來可能被讀取的資料並提前載入到記憶體中,這樣當這部分資料被請求時,就可以直接從記憶體中讀取,而不必等待磁碟I/O操作,從而降低延遲並提高資料讀取效率。

  • 在Linux核心5.4版本之前,NFS檔案系統的預讀量通常會基於掛載時設定的rsize 參數(即每次NFS讀請求的大小)。預設情況下,NFS的預讀視窗read_ahead_kb大小被設定為rsize 參數的15倍。Alibaba Cloud Linux 2的核心版本是4.19,預設的rsize參數大小為1,024 KB,即read_ahead_kb大小為15,360 KB。

  • 然而,在Linux核心5.4版本中引入了一個提交(index : kernel/git/torvalds/linux.git),隨後read_ahead_kb的值不再基於rsize參數,而是與VM_READAHEAD_PAGES參數相關。Alibaba Cloud Linux 3的核心版本是5.10,預設的read_ahead_kb大小為128 KB。

所以,Alibaba Cloud Linux 3相比於Alibaba Cloud Linux 2的讀取檔案效能有所下降。因此Alibaba Cloud Linux 3需要重新評估和調整預讀視窗大小,以最佳化檔案的讀取效率。

重要

在NFS檔案系統中,較大的預讀視窗可能會提高大型檔案連續讀取的效能,但如果視窗太大,也可能導致不必要的資料被載入到記憶體中,尤其是在隨機讀取的情境中。因此建議您根據實際的業務情境,仔細評估實際的工作負載,調整read_ahead_kb參數值以確保找到最佳的預讀視窗大小。

解決方案

您可以選擇以下任意一種方式修改read_ahead_kb參數來設定預讀值。

通過echo命令修改(單個檔案系統修改)

  1. 查看NFS系統目標裝置當前的預讀參數。

    cat /sys/class/bdi/$(mountpoint -d <nfs_mountpoint>)/read_ahead_kb

    其中<nfs_mountpoint>需替換為實際的NFS掛載點路徑,可以通過cat /proc/self/mountinfo命令擷取。

  2. 適當調大NFS檔案系統所對應裝置的預讀參數。

    sudo sh -c 'echo <num> > /sys/class/bdi/<major>:<minor>/read_ahead_kb'

    您需要根據實際環境替換以下參數:

    • <num>:需要設定的預讀視窗大小(單位KB)。

    • <major>:<minor>:NFS檔案系統的主要和次要裝置號,可以通過sudo mountpoint -d <nfs_mountpoint>命令擷取。

    例如:

    sudo sh -c 'echo 15360 > /sys/class/bdi/0:422/read_ahead_kb'
    說明

    如果您掛載了多個NFS檔案系統,需要重複執行命令修改每一個裝置的預讀參數。

通過udev機制自動修改(多個檔案系統修改)

您也可以利用udev機制,添加udev規則,為所有已掛載的裝置手動觸發一次udev事件,使其觸發udev規則檢查並自動修改預讀參數,也可以使後續新掛載的檔案卷自動修改其預讀參數。操作步驟如下:

說明

udev(使用者空間裝置管理員)是Linux核心的一個子系統,負責裝置節點的管理和自動化。udev機制的核心組件是udev守護進程,它運行於使用者空間,並與核心通過uevent機制進行通訊。

  1. 開啟並編輯NFS的udev rules設定檔(位於/etc/udev/rules.d/目錄)。如果不存在udev rules設定檔,請先自行建立。例如:

    sudo vim /etc/udev/rules.d/99-nfs.rules
  2. 在開啟的檔案中,添加udev規則,以自動修改預讀參數。

    該樣本表示將read_ahead_kb的值設定為15,360 KB,您可以根據需要修改預讀參數。

    SUBSYSTEM=="bdi", ACTION=="add", PROGRAM="/bin/awk -v bdi=$kernel 'BEGIN{ret=1} {if ($4 == bdi) {ret=0}} END{exit ret}' /proc/fs/nfsfs/volumes", ATTR{read_ahead_kb}="15360"
  3. 儲存並關閉檔案。

  4. 重新載入udev規則,使新增規則生效。

    sudo udevadm control --reload
  5. 為所有已經掛載的裝置手動觸發一次udev事件,將已掛載裝置的read_ahead_kb值一併修改。

    sudo udevadm trigger -c add -s bdi

通過修改NFS的設定檔(2.3.3-57.0.1.al8.1及之後版本的多個檔案系統修改)

如果您的Alibaba Cloud Linux 3的NFS檔案系統版本是nfs-utils-2.3.3-57.0.1.al8.1及之後的版本(可以通過rpm -qa | grep nfs-utils命令查詢 ),可以通過修改NFS的設定檔來修改read_ahead_kb參數(位於 /etc/nfs.conf目錄 )。

  1. 開啟並編輯NFS的設定檔。

    sudo vim /etc/nfs.conf 
  2. 修改預設預讀值,然後儲存並關閉檔案。

    [nfsrahead]
    nfs=15000
    nfs4=16000

    請根據實際掛載的NFS檔案系統版本(nfs/nfsv4)修改對應參數值。nfs表示NFS檔案系統協議版本是3;nfs4表示NFS檔案系統協議版本是4,您可以通過mount -v | grep nfs命令查詢。

  3. 對於已掛載的NFS檔案系統,需要手動卸載後重新掛載使配置生效。

    sudo umount <nfs_mountpoint>
    sudo mount -t nfs -o vers=<NFS協議版本> <NFS伺服器位址> <nfs_mountpoint>