上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器的 Windows Server 2016 上调整 TCP Chimney Offload,避免高延迟网络下的性能下降

发布人:Minchunlin 发布时间:2025-09-05 10:16 阅读量:831


那天已经接近午夜,我坐在香港葵涌机房的冷通道里,抱着一台临时接上的笔记本,对着一台装着 Windows Server 2016 的物理服务器发呆。白天客户还在抱怨:“大文件从内地传到香港特别慢,经常断流,SMB 复制速率忽上忽下。”网络拨测 RTT 在 65–95ms 之间,按理说带宽 1–2Gbps 的跨境专线做长肥管道(LFN)优化应该能跑起来,但实际表现惨不忍睹。

我把工单翻了个遍,发现一个细节:这台机是几年前做的金镜像自动化部署,后来补丁滚了一轮又一轮,但TCP Chimney Offload 的策略却被一份古早 GPO 残留给“动过手”。这玩意儿在 Windows 时代变迁里地位微妙:理论上把 TCP 处理从主机栈卸到网卡,实际上很多驱动/路径组合在高延迟场景反而会抖。于是我做了一次“外科手术”——把 Chimney 关掉,配合 RSS、RSC 和 TCP 自动调谐做了一套系统性调优。下面是完整复盘。

我的现场环境与关键参数

  • 位置/线路:HK 机房(葵涌),上联 ToR:Arista 7050 系列,IDC 内部 10GbE,跨境专线 2×1Gbps 叠加,业务常见 RTT(华南 ↔ HK)约 65–95ms,去美西公网 RTT 140–180ms。
  • 主机:Dell PowerEdge 2U(双路 Xeon,128GB RAM)
  • 网卡:双口 10GbE(Intel X710-DA2),单口与 vLAN 业务平面绑定
  • 系统:Windows Server 2016 Standard(1607,长期打补丁)

典型业务:

  • SMB 文件分发(数十 GB 备份/镜像)
  • IIS 静态大对象下载(>1GB)
  • RDP/WinRM 管理面

问题描述:高 RTT 路径下吞吐上不去、速率锯齿、偶发短暂无流量(客户感知“断流”)

先说结论(给赶时间的你)

在 Windows Server 2016 上,优先关闭** TCP Chimney Offload**(全局 + 网卡),启用/核对 RSS、RSC、自动窗口调谐(Auto-Tuning)。

对高延迟且带宽充足的链路,考虑 Auto-Tuning = normal 或 experimental(需 A/B 实测);ECN 视路径设备支持再决定。

对某些老驱动/设备组合,禁用 LSO v2(LSO/GSO)能消除锯齿;新驱动能正常则保持开启以减轻 CPU。

所有改动需要配套验证:iperf3/robocopy/curl -w,并抓取 重传率、拥塞窗口 和 CPU 软中断 的变化。

原理速写:为什么要动 Chimney?

TCP Chimney Offload 的目标是把 TCP 会话处理卸载给 NIC/驱动(或半卸载),减轻 CPU,但在高 RTT/复杂路径里,卸载栈与主机 TCP 栈的行为偏差、驱动实现差异、以及某些中间设备的“奇葩”行为,会放大重传、乱序、窗口收缩等现象,表现为吞吐抖动和锯齿。

Windows Server 2016 时代,微软更推 RSS/RSC + 主机栈优化的路径。RSS(多核并行处理)、RSC(合并段减少包处理开销)与自动窗口调谐配合,通常比 Chimney 更稳。

高 BDP(带宽×时延)链路要大窗口才能跑满带宽;窗口调谐与拥塞控制策略(如 CTCP)在主机栈里更易于被正确管控与观测。

变更前检查(别上来就改)

1)查看全局 TCP/Offload 状态(双命令系路线)

# PowerShell 路线(推荐)
Get-NetTCPSetting | ft SettingName, CongestionProvider, AutoTuningLevelLocal
Get-NetOffloadGlobalSetting
Get-NetAdapterRss
Get-NetAdapterAdvancedProperty -Name "*10G*" | ft DisplayName,DisplayValue

# netsh 路线(通用)
netsh int tcp show global
netsh int ip show offload

关注这些字段:

  • Chimney Offload State
  • Receive-Side Scaling (RSS) State
  • Receive Segment Coalescing (RSC) State
  • Add-On Congestion Control Provider(在 2016 上通常可设为 CTCP)
  • Receive Window Auto-Tuning Level(disabled/restricted/normal/highlyrestricted/experimental)

2)采集基线数据

连通性/路径

# Windows 客户端/跳板上
ping <HK_SERVER_IP> -n 50
tracert <HK_SERVER_IP>

iperf3(建议双向)

# 服务器端
iperf3 -s
# 客户端(华南 IDC 或云主机)
iperf3 -c <HK_SERVER_IP> -p 5201 -t 60 -R --logfile iperf_before.log

SMB 拷贝

robocopy \\HK-SERVER\share C:\test\ /E /R:0 /W:0 /TEE /LOG:robo_before.log

HTTP 大对象

curl -o NUL -w "time_total:%{time_total}\nsize_download:%{size_download}\nspeed_download:%{speed_download}\n" http://<hk>/bigfile.img

实操步骤:从 Chimney 到稳态主机栈

建议在变更窗口操作,准备回滚手段。操作包含全局参数与网卡高级属性两层。

Step 1:全局关闭 TCP Chimney,校正主机栈策略

# 1) 关 Chimney
Set-NetOffloadGlobalSetting -Chimney Disabled
# netsh 等价:
# netsh int tcp set global chimney=disabled

# 2) 开 RSS(多核并行)
Enable-NetAdapterRss -Name "*10G*"

# 3) 开/核实 RSC(2016 原生对物理 NIC 的 RSC 支持因驱动而异,虚拟交换场景更常见)
Set-NetAdapterAdvancedProperty -Name "*10G*" -DisplayName "Receive Segment Coalescing (RSC)" -DisplayValue "Enabled" -ErrorAction SilentlyContinue

# 4) TCP 自动窗口调谐
netsh int tcp set global autotuninglevel=normal
# 若 BDP 很大且路径稳定,可试 experimental(务必 A/B 测):
# netsh int tcp set global autotuninglevel=experimental

# 5) 拥塞控制(2016 可用 CTCP)
netsh int tcp set global congestionprovider=ctcp

# 6) 视中间设备支持决定 ECN(默认关闭较稳)
# netsh int tcp set global ecncapability=enabled   # 仅在确认全路径支持时开启

提示:部分环境历史遗留可能通过注册表写过 EnableTCPChimney(HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters)。优先用 Set-NetOffloadGlobalSetting / netsh,如需清理,确保重启窗口与回滚计划。

Step 2:网卡高级属性对齐(驱动/固件很关键)

打开设备管理器 → 网络适配器 → 你的 10GbE 网卡 → 高级,建议:

  • RSS:Enabled(队列数视 CPU 设 8/16/32)
  • Interrupt Moderation:Enabled/Adaptive
  • Receive/Transmit Buffers:调高(如 1024/2048)
  • Large Send Offload v2 (IPv4/IPv6):优先保持 Enabled(新驱动稳定时减少 CPU);若观测到高 RTT 场景锯齿/断流,可临时置 Disabled 做 A/B
  • Checksum Offload:通常 Enabled(同上,个别古老设备链路可测后决定)
  • Jumbo Frame:仅端到端一致时开启(IDC 内网可 9000;公网/跨域链路保持 1500)

PowerShell 等效批量(示例):

$nic = "*10G*"
Enable-NetAdapterRss -Name $nic
Set-NetAdapterAdvancedProperty -Name $nic -DisplayName "Interrupt Moderation" -DisplayValue "Enabled"
Set-NetAdapterAdvancedProperty -Name $nic -DisplayName "Receive Buffers" -DisplayValue "2048" -ErrorAction SilentlyContinue
Set-NetAdapterAdvancedProperty -Name $nic -DisplayName "Transmit Buffers" -DisplayValue "2048" -ErrorAction SilentlyContinue
# 如需 A/B:
# Set-NetAdapterAdvancedProperty -Name $nic -DisplayName "Large Send Offload v2 (IPv4)" -DisplayValue "Disabled"
# Set-NetAdapterAdvancedProperty -Name $nic -DisplayName "Large Send Offload v2 (IPv6)" -DisplayValue "Disabled"

Step 3:重启网络栈或计划性重启

# 最稳是维护窗重启主机
Restart-Computer

# 无法重启时,重置 NIC(注意影响在线业务)
Disable-NetAdapter -Name "*10G*" -Confirm:$false
Start-Sleep -Seconds 3
Enable-NetAdapter -Name "*10G*"

验证与数据对比

我分别对 华南↔HK(RTT 70–90ms) 与 HK↔美西(RTT 150–170ms) 做了 3 轮对比,统计窗口 60 秒,结果抽样如下(单位简化):

1)iperf3(接收方向,-R)

场景 调整前(疑似 Chimney 在作祟) 调整后(Chimney Disabled + RSS/RSC+Auto-Tuning)
华南↔HK 210–380 Mbps,重传率 1.8–3.2%,速率呈锯齿 820–980 Mbps,重传率 <0.5%,速率平滑
HK↔美西 90–160 Mbps,偶发 3–5 秒“停顿” 320–420 Mbps,无明显停顿

iperf3 典型命令:iperf3 -c <HK_IP> -p 5201 -t 60 -R

2)SMB(robocopy 单文件 >10GB)

场景 调整前 调整后
华南↔HK 24–45 MB/s,日志见大量重试 95–115 MB/s,无异常重试
HK↔美西 12–20 MB/s 38–55 MB/s

3)HTTP 大对象下载(curl -w)

指标 调整前 调整后
speed_download 140–320 Mbps 700–950 Mbps
time_total(1GB) 28–60 s 8–12 s

4)CPU/软中断变化(PerfMon)

计数器 调整前 调整后
Processor(_Total)\% Privileged Time 18–24% 10–14%
Network Interface\Packets/sec 抖动 明显 平滑
TCPv4\Segments Retransmitted/sec 高峰值 > 1800 稳定 < 300

常见坑与现场解决

“我明明在 2016 上看不到 Chimney 影响?”
有些版本/补丁默认已是 disabled,但历史 GPO/镜像脚本可能又把它打开或写过注册表;更常见的是网卡 TOE/LSO 组合引发类似症状。结论:不要想当然,一定用命令看实际状态,并做 A/B。

RSC 在物理 NIC 上看不到?
与驱动/固件相关,部分只在 vSwitch/vNIC 场景生效。没关系,关键是RSS + 窗口调谐,RSC 只是锦上添花。

LSO v2 开着时吞吐锯齿
老驱动偶发。先确认已关 Chimney,再对 LSO v2 做 A/B。我的现场中,美西高 RTT 路径关掉 LSO 后速率稳定性更好,但 CPU 增加了 2–4%。可接受的话就这么用,或升级驱动再回开。

ECN 开了更差
中间设备对 ECN 支持不一致,默认别开。只有确认端到端设备都支持时再启用。

拥塞控制到底用谁?
在 2016 上把 congestionprovider=ctcp 通常是正解。新系统(如 2019+)默认拥塞算法变化更大,另当别论。

注册表修过忘了重启
netsh/PowerShell 的大多数全局项即时生效,但注册表项需要重启才可 100% 一致。生产上要么只走 Set-*/netsh,要么安排重启。

一键回滚(出问题时)

# 回滚主机栈
netsh int tcp set global chimney=default    # 或 disabled → default
netsh int tcp set global autotuninglevel=normal
netsh int tcp set global congestionprovider=none
# 网卡相关(按需)
Set-NetAdapterAdvancedProperty -Name "*10G*" -DisplayName "Large Send Offload v2 (IPv4)" -DisplayValue "Enabled"
Set-NetAdapterAdvancedProperty -Name "*10G*" -DisplayName "Large Send Offload v2 (IPv6)" -DisplayValue "Enabled"
# 如修改过 RSS/RSC 再相应回调

生产经验:保留变更前导出

netsh int tcp show global > C:\prechange_tcp.txt
Get-NetOffloadGlobalSetting | Out-File C:\prechange_offload.txt
Get-NetAdapterAdvancedProperty -Name "*10G*" | Export-Csv C:\prechange_nic.csv -NoTypeInformation

最后给你一份可复制的“高延迟链路优化清单”

  •  Chimney Offload 全局 Disabled
  •  RSS Enabled(队列合理)
  •  Auto-Tuning = normal(必要时试 experimental 并 A/B)
  •  congestionprovider=ctcp(2016 推荐)
  •  RSC 能开则开(不强求)
  •  LSO v2 先保持 Enabled,遇到锯齿再 A/B
  •  Buffer/Interrupt Moderation 优化
  •  Jumbo 仅端到端一致才开
  •  iperf3/robocopy/curl 三板斧验证 + PerfMon 观测
  •  预留回滚与日志留存

现场日志片段(摘抄)

netsh int tcp show global 变更前:

Chimney Offload State                    : automatic
Receive-Side Scaling State               : enabled
Receive Window Auto-Tuning Level         : restricted
Add-On Congestion Control Provider       : none

变更后:

Chimney Offload State                    : disabled
Receive-Side Scaling State               : enabled
Receive Window Auto-Tuning Level         : normal
Add-On Congestion Control Provider       : ctcp

凌晨两点出头,我在冷通道里把最后一轮 iperf3 的日志收好,曲线终于像心电图回了正态,客户那头的运维在电话里“咦”了一声:“刚才那批镜像,速度稳了,连断流都没了。”我合上笔记本,抬头看着机柜上那串熟悉的资产标签,忽然想起几年前第一次在这台机子前做上线——同一台服务器、不同的操作系统策略,会带来完全不同的网络气质。

后来我把这个变更整理成标准化 Runbook:先关 Chimney,再让 RSS/RSC 和主机栈发力,必要时对 LSO/ECN/窗口调谐做 A/B。每次跨境、跨洋的长肥管道优化,我都先从这张清单开始。它不是万能钥匙,但大多数时候,它能把问题从“玄学”拉回到工程学。

如果你也正被“高延迟 + 吞吐抖动”折磨,按上面的步骤走一遍。别迷信某个单点开关,网络优化是系统工程——只要数据说话,你就会在日志里亲眼看到它变好。祝你那一夜,也能早点下班。

目录结构
全文