排查 Azure 文件存储性能问题

注意

本文中引用的 CentOS 是 Linux 分发版,将达到生命周期结束(EOL)。 请相应地考虑使用和规划。 有关详细信息,请参阅 CentOS 生命周期指南

本文列出了与 Azure 文件共享性能相关的常见问题,并介绍可能的原因和解决方法。 若要充分利用此故障排除指南,建议首先阅读了解 Azure 文件存储性能

适用于

文件共享类型 SMB NFS
标准文件共享 (GPv2)、LRS/ZRS
标准文件共享 (GPv2)、GRS/GZRS
高级文件共享 (FileStorage)、LRS/ZRS

常规性能故障排除

首先,针对性能问题的一些常见原因进行排查。

运行的是旧操作系统

如果客户端虚拟机 (VM) 运行Windows 8.1或 Windows Server 2012 R2,或较旧的 Linux 发行版或内核,则访问 Azure 文件共享时可能会遇到性能问题。 升级客户端 OS 或应用以下修补程序。

Windows 8.1 和 Windows Server 2012 R2 的注意事项

运行 Windows 8.1 或 Windows Server 2012 R2 的客户端为 I/O 密集型工作负载访问 Azure 文件共享时,经历的延迟可能会高于预期。 请确保已安装 KB3114025 修补程序。 此修补程序可提升创建和关闭句柄的性能。

可运行以下脚本,检查是否已安装此修补程序:

reg query HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters\Policies

如果安装了该修补程序,会显示以下输出:

HKEY_Local_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters\Policies {96c345ef-3cac-477b-8fcd-bea1a564241c} REG_DWORD 0x1

注意

自 2015 年 12 月起,Azure 市场中的 Windows Server 2012 R2 映像将默认安装修补程序 KB3114025。

你的工作负载受到限制

当达到文件共享的每秒 I/O 操作数 (IOPS)、流入量或流出量限制时,将会限制请求。 例如,如果客户端超过基线 IOPS,就会受 Azure 文件存储服务的限制。 限制可能会导致客户端性能不佳。

若要了解标准文件共享和高级文件共享的限制,请参阅文件共享和文件缩放目标。 根据工作负载的情况,通常可以通过从标准 Azure 文件共享迁移到高级 Azure 文件共享来避免限制。

若要详细了解共享级别或存储帐户级别的限制会如何导致高延迟、低吞吐量和一般性能问题,请参阅共享或存储帐户受限

高延迟、低吞吐量或低 IOPS

原因 1:共享或存储帐户受到限制

若要确认共享或存储帐户是否受到限制,可以访问并使用门户中的 Azure 指标。 还可以创建警报,在共享受到限制或即将受到限制时收到通知。 请参阅通过创建警报排查 Azure 文件存储问题

重要

对于标准存储帐户,限制发生在存储帐户级别。 对于高级文件共享,限制发生在共享级别。

  1. 在 Azure 门户中转到自己的存储帐户。

  2. 在左侧窗格中的“监视”下,选择“指标” 。

  3. 选择“文件”作为存储帐户范围的指标命名空间。

  4. 选择“事务”作为指标。

  5. 添加一个“响应类型”筛选器,然后检查是否有任何请求被限制。

    对于标准文件共享,如果请求在客户端帐户级别受到限制,则会记录以下响应类型:

    • ClientAccountRequestThrottlingError
    • ClientAccountBandwidthThrottlingError

    对于高级文件共享,如果某个请求在共享级别受限,则会记录以下响应类型:

    • SuccessWithShareEgressThrottling
    • SuccessWithShareIngressThrottling
    • SuccessWithShareIopsThrottling
    • ClientShareEgressThrottlingError
    • ClientShareIngressThrottlingError
    • ClientShareIopsThrottlingError

    如果已使用 Kerberos 对受限制的请求进行身份验证,你可能会看到一个指示身份验证协议的前缀,例如:

    • KerberosSuccessWithShareEgressThrottling
    • KerberosSuccessWithShareIngressThrottling

    若要详细了解每个响应类型,请参阅指标维度

    显示“响应类型”属性筛选器的屏幕截图。

解决方案

如果使用的是高级文件共享,请增加预配的文件共享大小,以便提高 IOPS 限制。 若要了解详细信息,请参阅了解高级文件共享的预配

原因 2:元数据或命名空间工作负载繁重

如果大多数请求是以元数据为中心(如 createfileopenfileclosefilequeryinfoquerydirectory),那么延迟情况将会比读取/写入操作更加严重。

若要确定你的大多数请求是否以元数据为中心,请先按照先前“原因 1”中概述的步骤 1-4 进行操作。 对于步骤 5,请不要添加“响应类型”筛选器,而是添加“API 名称”属性筛选器 。

显示“API 名称”属性筛选器的屏幕截图。

解决方法

  • 检查是否可以修改应用程序以减少元数据操作的数量。

  • 如果使用高级 SMB Azure 文件共享,请使用 元数据缓存

  • 在同一存储帐户中将文件共享划分为多个文件共享。

  • 将虚拟硬盘 (VHD) 添加到文件共享上,并从客户端装载 VHD,以便对数据执行文件操作。 此方法适用于单个编写器/读取器方案或包含多个读取器且无编写器的方案。 由于文件系统由客户端而不是 Azure 文件存储拥有,因此元数据操作可在本地执行。 安装程序提供的性能与本地直连的存储的性能类似。 但是,由于数据位于 VHD 中,因此无法通过除 SMB 装载以外的任何其他方式(例如通过 REST API 或 Azure 门户)访问这些数据。

    1. 在需要访问 Azure 文件共享的计算机中,使用存储帐户密钥装载文件共享,并将其映射到可用的网络驱动器(例如 Z:)。
    2. 转到“磁盘管理”,然后选择“操作”>“创建 VHD”。
    3. 将“位置”设置为 Azure 文件共享映射到的网络驱动器,根据需要设置“虚拟硬盘大小”,然后选择“固定大小”。
    4. 选择“确定” 。 VHD 创建完成后,它将自动装载,并显示新的未分配磁盘。
    5. 右键单击新的未知磁盘并选择“初始化磁盘”。
    6. 右键单击未分配的区域并创建新的简单卷。
    7. “磁盘管理”中应会出现一个新的驱动器号(例如 E:),表示此 VHD 具有读/写访问权限。 在“文件资源管理器”中,应会在映射的 Azure 文件共享网络驱动器(在本示例中为 Z:)上看到新 VHD。 为明确起见,应会显示两个驱动器号:Z: 上的标准 Azure 文件共享网络映射,以及 E: 驱动器上的 VHD 映射。
    8. 与 Azure 文件共享映射驱动器 (Z:) 相比,针对 VHD 映射驱动器 (E:) 上的文件执行繁重的元数据操作时性能会有明显的提高。 如果需要,可以断开连接映射的网络驱动器 (Z:),并照常访问装载的 VHD 驱动器 (E:)。
    • 若要在 Windows 客户端上装载 VHD,还可以使用 Mount-DiskImage PowerShell cmdlet。
    • 若要在 Linux 上装载 VHD,请参阅 Linux 发行版的文档。 下面是一个示例

原因 3:单线程应用程序

如果使用的应用程序是单线程的,则此安装程序可能会导致 IOPS 吞吐量明显低于最大可能的吞吐量,具体取决于预配的共享大小。

解决方案

  • 通过增加线程数来提高应用程序的并行度。
  • 切换到支持并行度的应用程序。 例如,对于复制操作,可以在 Windows 客户端中使用 AzCopy 或 RoboCopy,或者在 Linux 客户端中使用 parallel 命令。

原因 4:SMB 通道数超过 4 个

如果使用的是 SMB 多通道并且通道数超过 4 个,则会导致性能不佳。 若要确定连接计数是否超过 4 个,请使用 PowerShell cmdlet get-SmbClientConfiguration 查看当前的连接计数设置。

解决方案

为 SMB 设置单个 NIC 的 Windows 设置,使总通道数不超过 4 个。 例如,如果你有 2 个 NIC,则可以使用以下 PowerShell cmdlet 将单个 NIC 的最大值设置为 2:Set-SmbClientConfiguration -ConnectionCountPerRssNetworkInterface 2

原因 5:预读大小太小(仅限 NFS)

从 Linux 内核版本 5.4 开始,Linux NFS 客户端使用默认值 read_ahead_kb 128 kibibytes (KiB)。 此小值可能会减少大型文件的读取吞吐量。

解决方案

建议将 read_ahead_kb 内核参数值增加到 15 个兆字节(MiB)。 若要更改此值,请在 Linux 内核设备管理器 udev 中添加规则来持久设置预读大小。 执行以下步骤:

  1. 在文本编辑器中,通过输入并保存以下文本来创建 /etc/udev/rules.d/99-nfs.rules 文件:

    SUBSYSTEM=="bdi" \
    , ACTION=="add" \
    , PROGRAM="/usr/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"
    
  2. 在控制台中,通过以超级用户身份运行 udevadm 命令并重新加载规则文件和其他数据库来应用 udev 规则。 若要使 udev 知道新文件,只需运行此命令一次。

    sudo udevadm control --reload
    

请求的延迟很高

原因

客户端 VM 所在的区域可能与文件共享所在的区域不同。 高延迟的其他原因可能是由于客户端或网络造成的延迟。

解决方案

  • 从与文件共享位于同一区域的 VM 运行应用程序。
  • 对于存储帐户,可通过 Azure 门户中的 Azure Monitor 查看事务指标 SuccessE2ELatency 和 SuccessServerLatency。 SuccessE2ELatency 和 SuccessServerLatency 指标值之间的较大差异表示可能由网络或客户端引起的延迟。 请参阅 Azure 文件存储监视数据参考中的事务指标

客户端无法实现网络支持的最大吞吐量

原因

一个可能原因是缺少用于标准文件共享的 SMB 多通道支持。 目前,Azure 文件存储仅支持在单个通道上使用标准文件共享,因此从客户端 VM 到服务器只有一个连接。 此单一连接限定为客户端 VM 上的单一核心,因此,可从 VM 实现的最大吞吐量受限于单个核心。

解决方法

Linux VM 上装载的 Azure 文件共享的性能低下

原因 1:缓存

性能低下的一个可能原因是禁用了缓存。 如果重复访问文件,则缓存非常有用。 否则,可能是开销。 在禁用缓存之前,请检查是否正在使用缓存。

原因 1 的解决方案

若要检查缓存是否已禁用,请查找 cache= 条目。

Cache=none 指示缓存已禁用。 通过使用默认装载命令或显式将选项添加到 cache=strict 装载命令来重新装载共享,以确保启用默认缓存或“严格”缓存模式。

在某些情况下, serverino 装载选项可能会导致 ls 命令针对每个目录条目运行 stat 。 当列出大型目录时,此行为会导致性能降级。 可在 /etc/fstab 条目中检查装载选项:

//azureuser.file.core.windows.net/cifs /cifs cifs vers=2.1,serverino,username=xxx,password=xxx,dir_mode=0777,file_mode=0777

还可以通过运行 sudo mount | grep cifs 命令并检查其输出来检查是否使用了正确的选项。 下面是一个示例输出:

//azureuser.file.core.windows.net/cifs on /cifs type cifs (rw,relatime,vers=2.1,sec=ntlmssp,cache=strict,username=xxx,domain=X,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.10.1,file_mode=0777, dir_mode=0777,persistenthandles,nounix,serverino,mapposix,rsize=1048576,wsize=1048576,actimeo=1)

如果不存在或cache=strictserverino选项,请从文档中运行装载命令,再次卸载并装载Azure 文件存储。 然后,重新检查 /etc/fstab 条目是否具有正确的选项。

原因 2:限制

你可能遇到限制,并且请求将发送到队列。 可以利用 Azure Monitor 中的 Azure 存储指标对此进行验证。 还可以创建警报,以在共享受到限制或即将受到限制时通知你。 请参阅通过创建警报排查 Azure 文件存储问题

原因 2 的解决方案

确保应用在 Azure 文件存储缩放目标中。 如果使用的是标准 Azure 文件共享,可考虑转换到高级版。

Linux 客户端上的吞吐量低于 Windows 客户端上的吞吐量

原因

这是在 Linux 上实现 SMB 客户端的已知问题。

解决方法

  • 跨多个 VM 分散负载。
  • 在同一 VM 上,通过 nosharesock 选项使用多个装入点,并将负载分散到这些装入点上。
  • 在 Linux 上,尝试使用 nostrictsync 选项进行装载,以避免每次调用 fsync 时都强制执行 SMB 刷新。 对于 Azure 文件存储,此选项不会影响数据一致性,但可能会导致目录列表(ls -l 命令)中出现过时的文件元数据。 使用 stat 命令直接查询文件元数据将会返回最新的文件元数据。

涉及大量打开/关闭操作的元数据密集型工作负载的延迟较高

原因

缺少目录租约支持。

解决方法

  • 如果可能,请避免短时间内在同一目录中使用过多的打开/关闭句柄。
  • 对于 Linux VM,请指定“actimeo=<sec>”作为装载选项,以延长目录条目缓存超时。 默认情况下,超时值为 1 秒,因此较大的值(例如 30 秒)可能会有所帮助。
  • 对于 CentOS Linux 或 Red Hat Enterprise Linux (RHEL) VM,请将系统升级到 CentOS Linux 8.2 或 RHEL 8.2。 对于其他 Linux 发行版,请将内核升级到 5.0 或更高版本。

文件和文件夹的枚举速度变慢

原因

如果客户端计算机上用于大型目录的缓存不足,则可能会出现此问题。

解决方案

若要解决此问题,请 DirectoryCacheEntrySizeMax 调整注册表值,以允许在客户端计算机中缓存更大的目录列表:

  • 位置:HKEY_LOCAL_MACHINE\System\CCS\Services\Lanmanworkstation\Parameters
  • 值名称:DirectoryCacheEntrySizeMax
  • 值类型:DWORD

例如,可以将其设置为 0x100000 并查看性能是否提高。

将文件复制到 Azure 文件共享以及从中复制文件时速度缓慢

尝试将文件传输到 Azure 文件服务时,可能会发现速度缓慢。 如果你没有特定的 I/O 大小下限要求,我们建议使用 1 MiB 的 I/O 大小以获得最佳性能。

在 Windows 中将文件复制到 Azure 文件以及从中复制文件时速度缓慢

  • 如果知道使用写入进行扩展的文件的最终大小,并且当文件上未写的尾部包含零时,软件没有兼容性问题,则提前设置文件大小,而不是使每次写入都成为扩展写入。

  • 使用正确的复制方法:

    • 为两个文件共享之间的任何传输使用 AzCopy
    • 在本地计算机上的文件共享之间使用 Robocopy

过多的 DirectoryOpen/DirectoryClose 调用

原因

如果最频繁的 API 调用中包括 DirectoryOpen/DirectoryClose 调用,而你预计客户端不会发出这么多的调用,则问题可能是 Azure 客户端 VM 上安装的防病毒软件引起的。

解决方法

Windows 四月平台更新中提供了此问题的修复措施。

SMB 多通道未触发

原因

最近对 SMB 多通道配置设置进行了更改,但没有重新装载。

解决方案

  • 对 Windows SMB 客户端或帐户 SMB 多通道配置设置进行任何更改后,必须卸载该共享,等待 60 秒,并重新装载该共享以触发多通道。
  • 对于 Windows 客户端 OS,生成具有高队列深度(如 QD=8)的 IO 负载(例如复制文件)以触发 SMB 多通道。 对于服务器 OS,在 QD=1 时触发 SMB 多通道,这意味着一旦启动对共享的任何 IO,就会触发 SMB 多通道。

解压缩文件时性能降低

根据使用的确切压缩方法和解压缩操作,在 Azure 文件共享上执行解压缩操作的速度可能比在本地磁盘上慢。 这通常是因为解压缩工具在对压缩档案进行解压缩的过程中会执行许多元数据操作。 为获得最佳性能,我们建议将压缩存档从 Azure 文件共享复制到本地磁盘,在那里解压缩,然后使用 Robocopy(或 AzCopy)等复制工具复制回 Azure 文件共享。 使用像 Robocopy 这样的复制工具可以通过使用多个线程并行复制数据来弥补 Azure 文件存储中元数据操作相对于本地磁盘的性能下降。

托管文件共享的网站上的高延迟

原因

文件共享上的大量文件更改通知可能会导致高延迟。 这通常发生在托管具有深层嵌套目录结构的文件共享的网站上。 一个典型场景是 IIS 托管的 Web 应用程序,其中在默认配置中为每个目录设置了文件更改通知。 已注册客户端的共享上的每个更改 (ReadDirectoryChangesW) 都会将更改通知从文件服务推送到客户端,这会占用系统资源,并且随着更改数量的增加问题会变得更加严重。 这会导致共享限制,从而导致更高的客户端延迟。

若要进行确认,可以使用门户中的 Azure 指标。

  1. 在 Azure 门户中转到自己的存储帐户。
  2. 在左侧菜单中的“监视”下,选择“指标”。
  3. 选择“文件”作为存储帐户范围的指标命名空间。
  4. 选择“事务”作为指标。
  5. 添加 ResponseType 的筛选器,并检查是否有任何请求具有响应代码SuccessWithThrottling(对于 SMB 或 NFS)或ClientThrottlingError(对于 REST)。

解决方案

  • 如果未使用文件更改通知,请禁用文件更改通知(首选)。

    • 更新 FCNMode 以禁用文件更改通知
    • 通过在注册表中设置 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3SVC\Parameters\ConfigPollMilliSeconds 来将 IIS 工作进程 (W3WP) 轮询间隔更新为 0,然后重启 W3WP 进程。 若要了解有关此设置的详细信息,请参阅 IIS 的许多部分使用的常见注册表项
  • 增加文件更改通知轮询间隔的频率以减少卷。

    根据要求将 W3WP 工作进程轮询间隔更新为更高的值(例如 10 或 30 分钟)。 在注册表中设置 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3SVC\Parameters\ConfigPollMilliSeconds,并重启 W3WP 进程。

  • 如果网站的映射物理目录具有嵌套目录结构,则可以尝试限制文件更改通知的范围以减少通知量。 默认情况下,IIS 使用虚拟 目录映射到的物理目录中的 Web.config 文件中的配置,以及该物理目录中的任何子目录中的配置。 如果不想在子目录中使用 Web.config 文件,请 false 指定 allowSubDirConfig 虚拟目录中的属性。 此处提供了更多详细信息。

    将 Web.Config 中的 IIS 虚拟目录allowSubDirConfig设置设置为false从范围中排除映射的物理子目录。

另请参阅

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区