Azure虚拟机(VM)具有可以优化的默认网络设置,以提高吞吐量和一致性。 本文介绍如何优化 Windows 和 Linux VM 的网络性能。
重要
本文中所述的许多优化(例如,拥塞控制、队列规则、缓冲区大小和 NIC 优化)会影响系统之间的流量流动方式。
为了获得最佳效果,请在整个参与工作负荷的所有虚拟机上一致地应用这些设置,包括:
- 客户端系统
- 服务器系统
仅将这些配置应用于一部分虚拟机可能会导致:
- 吞吐量不一致
- 数据包重传增加
- 不理想的拥塞表现
始终验证整个数据路径中的更改并测试端到端性能。
Windows 虚拟机
如果 Windows VM 支持加速网络,请启用该功能以实现最佳吞吐量。 有关详细信息,请参阅创建具有加速网络的 Windows VM。
对于所有其他Windows VM,接收端缩放(RSS)可以提供比没有 RSS 的 VM 更高的最大吞吐量。 默认情况下可能会禁用 RSS。 若要检查 RSS 是否已启用并启用它,请执行以下步骤:
使用 Get-NetAdapterRss PowerShell 命令检查是否为网络适配器启用了 RSS。 在以下示例中,来自
Get-NetAdapterRss的输出表明 RSS 尚未启用。Name : Ethernet InterfaceDescription : Microsoft Hyper-V Network Adapter Enabled : False输入以下命令以启用 RSS:
Get-NetAdapter | % {Enable-NetAdapterRss -Name $_.Name}此命令没有输出。 它更改网络接口卡(NIC)设置,并导致临时连接丢失约一分钟。 在连接丢失期间显示“正在重新连接”对话框。 通常在第三次尝试后,连接会还原。
再次输入
Get-NetAdapterRss命令,确认 RSS 在 VM 中已启用。 如果成功,将返回以下示例输出:Name : Ethernet InterfaceDescription : Microsoft Hyper-V Network Adapter Enabled : True
Linux 虚拟机
RSS 默认在 Azure 的 Linux 虚拟机(VM)中启用。 自 2017 年 10 月发布的 Linux 内核包括其他网络优化选项,可帮助 Linux VM 实现更高的吞吐量。
启用 Azure 加速网络以实现最佳吞吐量
Azure加速网络可以显著提高吞吐量并减少延迟和抖动。
Azure优化内核
某些发行版(例如 Ubuntu(Canonical)和 SUSE)提供 针对 Azure 调优的内核。
使用以下命令验证你使用的是Azure内核,该内核通常包括在azure内核名称中。
uname -r
# Sample output for an Azure kernel on an Ubuntu Linux VM
6.8.0-1017-azure
在 Azure 中的 Linux VM 中实现一致的传输速度
Linux VM 可能出现不一致的传输速度,尤其是在大型区域传输期间。 常见原因包括较旧的内核、默认缓冲区大小和未调整的拥塞控制或队列规则设置。
将以下基线优化应用于Azure上的任何 Linux VM。 这是三个不同的方面 - 应用所有这些方面,而不仅仅是其中一个:
- 拥塞控制和 qdisc 测试:TCP 拥塞控制算法和队列规则(qdisc)。
-
NIC 环缓冲区大小:网络接口级别的 RX/TX 环缓冲区大小调整,独立于
sysctl。 -
Sysctl 参数:应用于
sysctl的一组最小 Azure 特定/etc/sysctl.d/99-azure-network-tuning.conf参数。
拥塞控制和 qdisc 测试
注释
BBR 支持仅适用于内核 4.19 及更高版本。
拥塞控制和 qdisc 设置会影响流量端到端的流动方式。 它们可能会像缓冲区大小一样,对吞吐量和延迟产生同样大的影响。 测试这些组合,并保留最适合您的工作负载的组合。
一般指南:
- 如果你的体系结构跨越不同的Azure区域(长途、更高的延迟路径),BBR 通常更合适。
- 对于区域或可用性区域中的区域内通信(低延迟路径),CUBIC 通常就足够了。
此外,还要使用 BBR 对 fq 和 pfifo_fast 两种 qdisc 都进行测试,因为 qdisc 的选择对结果的影响可能与拥塞控制算法本身一样大。
-
BBR + FQ (通常为高吞吐量和长途传输的强默认值)
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr sudo sysctl -w net.core.default_qdisc=fq -
BBR + PFIFO_FAST (可用于比较突发或混合流量下的队列行为)
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr sudo sysctl -w net.core.default_qdisc=pfifo_fast -
CUBIC + PFIFO_FAST (本地化、低延迟通信的常见基线)
sudo sysctl -w net.ipv4.tcp_congestion_control=cubic sudo sysctl -w net.core.default_qdisc=pfifo_fast
用具有代表性的流量分别测试各个选项,然后针对您的环境采用性能最佳的组合。
重要
sysctl -w上述命令会立即应用,但不会在重新启动时保留。 确定组合后,通过将以下行添加到 /etc/sysctl.d/99-azure-congestion.conf 中来使其持久化(以 BBR + FQ 为例;请替换为你选择的组合):
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
然后应用更改: sudo sysctl --system
注释
pfifo_fast 可用性可能因发行版/内核而异。 如果不可用,请在环境中使用最接近支持的 qdisc 选项并继续基准测试。
NIC 环缓冲区大小
优化 NIC 环缓冲区是Azure上任何 Linux VM 的基线要求。 以下设置在网络接口级别应用,而不是通过 sysctl。
RX/TX 环形缓冲区是 NIC 驱动程序用来保存从(或正等待发送到线路上的)线路到达的数据包的内存区域,然后内核有机会处理它们。 当 CPU 暂时繁忙(例如,处理中断风暴、调度延迟或其他流量突发)时,更大的环形缓冲区为驱动程序提供更多空间来保持传入或传出数据包排队,而不是丢弃这些数据包。 丢包会导致间歇性超时,并在突发或高并发流量下发生重传。 此环形缓冲区概念与 / 中为 -G--set-ring 和 -g/--show-ring 选项记录的 RX/TX 环相同。 代价是延迟增加:更大的缓冲区可以吸收更大的突发,但在处理之前在队列中停留更久的数据包也会增加延迟。 将环形缓冲区大小视为丢包容忍度和延迟之间的平衡,而不是“越大越好”。
# Accelerated Networking interface (mlx4_en, mlx5_core, or mana, depending on the VM SKU)
sudo ethtool -G <accel-interface> rx 4096 tx 4096
# Synthetic (hv_netvsc) interface
sudo ethtool -G <synthetic-interface> rx 1024 tx 1024
重要
在 SUSE Linux Enterprise Server(SLES)上,处于高负载状态的 SAP HANA 系统和其他高并发、多线程工作负载可能会触发加速网络环形缓冲区饱和。 即使接口计数器显示没有丢包或错误,此条件也会显示为间歇性连接超时(rc=110/ETIMEDOUT)。 这些工作负荷通常需要比本文所示的默认值更大的环形缓冲区值。 有关建议的 ethtool 值以及使这些值在重启后仍然保留的步骤(udev 规则和重建 initramfs),请参阅 SUSE 的 Azure 上因加速网络环形缓冲区饱和导致的间歇性网络连接超时(rc=110)。
重要
这些设置不会自行在重新启动时保留。 若要使其永久化,请添加 udev 规则,如 持久化 NIC 环缓冲区大小(RX/TX)中所述。
Sysctl 参数
将以下行添加到 /etc/sysctl.d/99-azure-network-tuning.conf。 大多数值都是安全的默认值,但有两组需要针对您的 VM 重新计算,而不是原样复制:
-
内存缩放值(
net.ipv4.tcp_mem,net.ipv4.udp_mem)用于根据总 RAM 设置网络堆栈的内存压力阈值(低、压力、最大值,以 4 KB 页为单位)。 显示的值假定 VM 的 RAM 大约为 4 GB。 将它们按比例纵向扩展(例如,大约为 8 GB RAM 的两倍),因此网络堆栈有足够的内存头空间,而不会耗尽 VM 上的其他工作负荷。 -
带宽缩放值(
net.core.rmem_max、net.core.wmem_max、net.ipv4.tcp_rmem、net.ipv4.tcp_wmem)将套接字缓冲区大小调整为连接的带宽延迟乘积:buffer size (bytes) ≈ (NIC bandwidth in bits/second ÷ 8) × round-trip time (seconds)显示的值假定使用约 12 Gbps 的加速网络接口和约 2 毫秒的往返时间,这在单个 Azure 区域内通信中是典型情况:(12,000,000,000 ÷ 8)× 0.002 ≈ 3,000,000 字节 ≈ 3 MB,这就是为什么rmem_max、wmem_max以及tcp_rmem/tcp_wmem的 max 字段设置为 3145728。 针对 VM 大小的实际 NIC 行速率(请参阅 按 VM 大小划分的加速网络吞吐量)以及工作负荷的预期往返时间(对于跨区域流量而言更高)重新计算。
# TCP memory pressure thresholds in 4-KB pages (low, pressure, max): pages = RAM bytes x fraction / 4096; shown values ≈ 9%/12.5%/19% of 4 GB RAM
net.ipv4.tcp_mem = 98304 131072 196608
# Same memory-pressure thresholds as tcp_mem, applied to UDP sockets
net.ipv4.udp_mem = 98304 131072 196608
# Max receive buffer per socket, sized to the bandwidth-delay product: (NIC bandwidth in bytes/sec) x RTT in seconds ≈ (12 Gbps / 8) x 0.002 s ≈ 3 MB
net.core.rmem_max = 3145728
# Max send buffer per socket; same bandwidth-delay product calculation as rmem_max
net.core.wmem_max = 3145728
# Per-socket TCP receive buffer (min, default, max bytes); max matches the bandwidth-delay product above
net.ipv4.tcp_rmem = 4096 87380 3145728
# Per-socket TCP send buffer (min, default, max bytes); max matches the bandwidth-delay product above
net.ipv4.tcp_wmem = 4096 65536 3145728
# Default receive buffer for sockets that don't request a larger size; kept modest so many concurrent sockets don't exhaust RAM on a 4 GB VM
net.core.rmem_default = 262144
# Default send buffer for sockets that don't request a larger size; same rationale as rmem_default
net.core.wmem_default = 262144
# Minimum guaranteed UDP receive buffer per socket, even under memory pressure
net.ipv4.udp_rmem_min = 16384
# Minimum guaranteed UDP send buffer per socket, even under memory pressure
net.ipv4.udp_wmem_min = 16384
# Max packets processed per NAPI polling cycle across all interfaces, per CPU pass; raised from the kernel default of 300 for high-throughput NICs
net.core.netdev_budget = 1000
# Max packets allowed to queue when the kernel can't drain the NIC's ring buffer fast enough
net.core.netdev_max_backlog = 32768
# Max packets processed per network device, per NAPI polling pass (64 is also the kernel default; listed here for explicitness)
net.core.dev_weight = 64
# Enable TCP timestamps (RFC 7323), needed for RTT estimation and required by tcp_tw_reuse below
net.ipv4.tcp_timestamps = 1
# Allow reusing TIME_WAIT sockets for new outgoing connections, reducing ephemeral port exhaustion under high connection churn
net.ipv4.tcp_tw_reuse = 1
# Widen the ephemeral source port range to support more concurrent outgoing connections
net.ipv4.ip_local_port_range = 1024 65535
# Max pending-connection backlog for listening sockets, raised for servers accepting many concurrent connection attempts
net.core.somaxconn = 32768
# Max ancillary (control message) buffer size per socket
net.core.optmem_max = 65535
# Disable F-RTO (Forward RTO-recovery), an algorithm for lossy/wireless links that's unnecessary on stable wired Azure networks
net.ipv4.tcp_frto = 0
# Microseconds to busy-poll a socket before sleeping, trading CPU time for lower latency on latency-sensitive workloads
net.core.busy_poll = 50
# Microseconds to busy-poll specifically during read() calls; used together with busy_poll
net.core.busy_read = 50
然后应用更改:
sudo sysctl --system
持久化 NIC 环形缓冲区大小(RX/TX)
在 /etc/udev/rules.d/99-azure-ring-buffer.rules 中创建 udev 规则,以将环形缓冲区设置应用于网络接口。 匹配 ENV{ID_NET_DRIVER} 可检测当前存在的加速网络驱动程序(mlx4_core 或 mlx5_core,取决于 VM SKU) without needing to know the driver ahead of time. Use rx 4096 tx 4096for Accelerated Networking interfaces and keeprx 1024 tx 1024for synthetichv_netvsc` 接口):
# Set up accelerated networking ring buffers (mlx4_core, or mlx5_core, depending on the VM SKU)
SUBSYSTEM=="net", ACTION=="add|move", ENV{ID_NET_DRIVER}=="mlx4_core", RUN+="/usr/sbin/ethtool -G %k rx 4096 tx 4096"
SUBSYSTEM=="net", ACTION=="add|move", ENV{ID_NET_DRIVER}=="mlx5_core", RUN+="/usr/sbin/ethtool -G %k rx 4096 tx 4096"
# Set up synthetic interface ring buffers (hv_netvsc)
SUBSYSTEM=="net", ACTION=="add|move", ENV{ID_NET_DRIVER}=="hv_netvsc", RUN+="/usr/sbin/ethtool -G %k rx 1024 tx 1024"
NIC 传输队列长度
在 /etc/udev/rules.d/99-azure-txqueue-len.rules 中创建以下规则以增加发送队列长度:
SUBSYSTEM=="net", ACTION=="add|change", KERNEL=="en*|eth*", ATTR{tx_queue_len}="10000"
测试 udev 规则而不重新启动
添加或更新环形缓冲区或传输队列长度 udev 规则后,无需重新启动即可将其应用到已存在的接口:
sudo udevadm control --reload-rules
sudo udevadm trigger --action=add --subsystem-match=net
此步骤会针对现有网络接口重新触发 udev 的 add 操作,因此规则会立即对其生效,而不是等待下一次启动或热插即用事件。 使用 ethtool -g <interface>(环形缓冲区)或 ip link show <interface>(传输队列长度)确认新值已生效。
SR-IOV 双接口行为和副作用
对于 Linux 上的高性能网络,Azure 使用 SR-IOV,VF 接口绑定到 mlx4_en 或 mlx5_core 驱动程序,具体取决于 VM SKU。 在此模型中,可以看到同一 VM 网络路径的合成接口和虚拟函数(VF)接口。
了解详细信息。
此设计是预期的,但如果这两个接口都被视为独立的数据路径,则优化和故障排除期间可能会造成混淆。
可能的副作用包括:
- 当设置应用于一个接口但流量使用另一个接口时,基准结果不一致。
- 在合成路径与 VF 路径之间进行故障转移期间,延迟意外飙升或发生重传。
- 如果从错误的接口收集计数器和抓包数据,则会导致诊断结果产生误导。
若要降低风险,请:
- 在调优之前,先确认哪个接口承载工作负载流量。
- 使 udev 和 sysctl 调优与接口策略保持一致。
- 重新启动、驱动程序更新或加速网络状态更改后重新测试吞吐量和延迟。
其他注释
系统管理员可以通过编辑配置文件(例如 /etc/sysctl.d/, /etc/modules-load.d/和 /etc/udev/rules.d/)来实现这些建议。 仔细查看内核和驱动程序更新以避免回归。
相关内容
- 使用邻近放置组将各个 VM 部署在相近的位置,以缩短延迟。
- 请通过带宽/吞吐量测试查看你的方案的优化后结果。
- 阅读有关如何为虚拟机分配带宽的信息。
- 阅读Azure 虚拟网络常见问题。