香港服务器使用 Windows Server 2012 时,如何优化 Windows Update 策略,避免高峰期更新导致的系统性能下降?

今年的“618”促销活动的前一周,香港葵涌机房的NOC 屏幕上红点子突然开始闪:IIS 响应时延拉长,队列长度飙升。打开一台前端节点,TiWorker.exe 和 TrustedInstaller.exe 抢占了 70% CPU,磁盘队列像电梯口一样拥挤。——不用想,Windows Update 正在自动装补丁,而时间恰好踩在晚间流量峰前的预热期。
那一晚,我把值守凳子挪到了这排服务器前,调 GPO、限 BITS、切 WSUS、加任务计划、改重启策略、做回滚脚本。第二天上午,业务峰值没再被“更新风暴”击穿。更重要的是,这套方法此后在我们一整批香港节点上落地成了标准。
接下来,我把那夜做过、后来复盘优化过的动作,完整写给你。
场景基线与目标
机房与硬件(示例)
机房:香港,BGP 线路,机内 10GbE,出口 2×10Gbps。
角色拆分:
WEB 前端:IIS 8.0(Windows Server 2012 Standard),Dell R630,2×E5-2680 v4 / 128GB RAM / 4×SATA SSD(RAID10)/ Intel X520 10GbE。
应用层:IIS + .NET 4.7.2。
数据库层:SQL Server 2014(单独维护窗口,本文聚焦 OS 更新)。
时间:以 HKT(UTC+8) 为准。业务峰一般 19:00–01:00 HKT。
痛点
高峰前后自动扫描/下载/安装补丁,TiWorker.exe 占 CPU,I/O 抢占,IIS 请求排队。
一些节点自动重启,负载不均衡。
目标
四层防护思路:源头(WSUS/审批)→ 下载(BITS 限速/时间窗)→ 安装(维护窗口/负载检查)→ 重启(有序可控/无感切换)。
约束:Server 2012(非 R2 也可按本流程),可引入 WSUS;无 SCCM 也能落地;要有回滚。
方案总览(一图胜千言)
四层防护
源头控流:WSUS 分环审批,减少无关补丁;
下行控速:BITS 按时间窗限速(白天低速、凌晨放开);
安装控时:GPO/自动维护锁定“02:00–05:00 HKT”;安装前脚本看负载,不达标就延后;
重启控序:先摘流/Drain,再安装,再健康检查,最后按批次重启;失败立即回滚。
实施步骤
先看现状与数据(务实)
在动任何策略前,我会跑一轮 24 小时观测,抓到“Update 干扰业务”的真实证据。
| 项目 | 峰前(18:00–20:00 HKT) | 安装期(随机触发) | 峰值(20:00–01:00 HKT) |
|---|---|---|---|
| CPU(P95) | 42% | 78%(有 TiWorker) | 65% |
| 磁盘队列长度(P95) | 0.7 | 3.1 | 1.5 |
| IIS 当前连接数(P95) | 3,500 | 下降/抖动 | 5,200 |
| P95 响应时间 | 180 ms | > 600 ms | 250 ms |
这张表是说服产品与老板给维护窗“让道”的最好材料。
1) 源头控流:WSUS + 分环审批
为什么:别让每台机器盲目去公网拉补丁;减少不相关补丁;可分批试水。
拓扑(建议)
在香港同机房上 WSUS 上游(或做一个香港下游 WSUS,上游在总部)。
同机房能够保证更新下载走内网,不占用宝贵的出口带宽。
审批策略(Rings)
Ring 0(Canary):1–2 台前端,先行。
Ring 1(边缘业务):10–20% 前端。
Ring 2(核心):剩余全部。
WSUS 操作要点
“产品与分类”只勾 Windows Server 2012 的 安全更新 / 关键更新;先取消驱动/预览版。
每周三(示例)统一同步 + 清理 + 自动拒绝过期。
按 Ring 分组机器,有节奏地批准。
WSUS 清理脚本(管理机上 PowerShell):
Add-PSSnapin UpdateServices
$wsus = Get-WsusServer -Name "wsus-hk-01" -PortNumber 8530
$cleanup = $wsus.GetCleanupManager()
$cleanup.PerformCleanup() # 释放磁盘、过期更新等
2) 下行控速:BITS 按时间窗限速
为什么:多数“高峰卡顿”是下载阶段抢带宽/占 I/O。用 BITS 限速,白天慢慢拉,凌晨全速冲。
GPO 路径
计算机配置 → 管理模板 → 网络 → Background Intelligent Transfer Service (BITS)
- 限制 BITS 后台传输的最大网络带宽:启用
- 工作时段(例如 08:00–23:00 HKT):512 Kbps–2 Mbps(看内网情况)
- 非工作时段(例如 23:00–07:59 HKT):不限制
BITS 限速只影响后台传输,正合适 Windows Update 的下载模型。
建议时间表(香港)
| 时间段 (HKT) | 策略 |
|---|---|
| 08:00–23:00 | BITS 限速 1 Mbps(示例) |
| 23:00–02:00 | 放宽到 10–50 Mbps(机内网足够时) |
| 02:00–05:00 | 不限制(维护窗) |
| 05:00–08:00 | 恢复限速 |
3) 安装控时:GPO + 自动维护 + 政策键值
A. 指向 WSUS
计算机配置 → 管理模板 → Windows 组件 → Windows Update
指定 Intranet Microsoft 更新服务位置:启用
设置 http://wsus-hk-01:8530(示例)
B. 配置自动更新安装时段
配置自动更新:启用 → 选 4 - 自动下载并按计划安装
计划安装日:0 - 每天(或周四)
计划安装时间:3(即 03:00 HKT)
针对已登录用户不自动重启:启用(RDS/堡垒机尤需)
自动更新检测频率:4 小时
重新计划计划安装:启用(延迟 15 分钟)
Server 2012 的“自动维护”也会调度更新,默认在闲时运行。你可以把维护时间固定到 03:00 HKT,避免“灵活”带来的惊喜。
设置自动维护时间(注册表):
# 维护时间:03:00 HKT
New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Maintenance" -Force | Out-Null
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Maintenance" `
-Name "MaintenanceStartTime" -PropertyType String -Value "03:00" -Force | Out-Null
(可选)用注册表直配 AU 策略(非首选,给应急用):
$wu = "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"
$au = Join-Path $wu "AU"
New-Item $wu -Force | Out-Null
New-Item $au -Force | Out-Null
New-ItemProperty $wu -Name "WUServer" -Value "http://wsus-hk-01:8530" -PropertyType String -Force | Out-Null
New-ItemProperty $wu -Name "WUStatusServer" -Value "http://wsus-hk-01:8530" -PropertyType String -Force | Out-Null
New-ItemProperty $au -Name "AUOptions" -Value 4 -PropertyType DWord -Force | Out-Null # 4=按计划安装
New-ItemProperty $au -Name "ScheduledInstallDay" -Value 0 -PropertyType DWord -Force | Out-Null # 每天
New-ItemProperty $au -Name "ScheduledInstallTime" -Value 3 -PropertyType DWord -Force | Out-Null # 03:00
New-ItemProperty $au -Name "NoAutoRebootWithLoggedOnUsers" -Value 1 -PropertyType DWord -Force | Out-Null
4) 安装前的“刹车线”:负载不达标就延后
思路:即便到了 03:00,也可能遇到夜间批处理/备份/长查询。安装前跑一个健康检查,阈值不满足就延期 30 分钟再试。
PowerShell 脚本(部署到每台,配合计划任务 02:55 运行):
# Check-And-Install-WindowsUpdate.ps1
param(
[int]$MaxCpuP95 = 60,
[int]$MaxDiskQLen = 1,
[int]$MaxIISConn = 2000,
[int]$RetryMinutes = 30
)
function Get-Metric {
$cpu = (Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 2 -MaxSamples 5).CounterSamples.CookedValue | Measure -Average | % Average
$dq = (Get-Counter '\PhysicalDisk(_Total)\Current Disk Queue Length' -SampleInterval 2 -MaxSamples 5).CounterSamples.CookedValue | Measure -Average | % Average
$iis = (Get-Counter '\Web Service(_Total)\Current Connections' -ErrorAction SilentlyContinue).CounterSamples.CookedValue | Measure -Average | % Average
[pscustomobject]@{ CPU=[int]$cpu; DiskQ=[int]$dq; IISConn=[int]$iis }
}
$metric = Get-Metric
Write-Host "CPU=$($metric.CPU) DiskQ=$($metric.DiskQ) IISConn=$($metric.IISConn)"
if($metric.CPU -gt $MaxCpuP95 -or $metric.DiskQ -gt $MaxDiskQLen -or $metric.IISConn -gt $MaxIISConn){
Write-Warning "Load too high, deferring update $RetryMinutes minutes."
Start-Sleep -Seconds ($RetryMinutes*60)
}
# 使用 PSWindowsUpdate(建议装 WMF5.1 后)
if(-not (Get-Module -ListAvailable PSWindowsUpdate)){
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
Install-Module PSWindowsUpdate -Force
}
# 只从 WSUS 安装已批准更新;拒绝驱动类;自动接受 EULA;不自动重启(重启交由 drain 逻辑)
Import-Module PSWindowsUpdate
Get-WindowsUpdate -MicrosoftUpdate -Category 'SecurityUpdates','CriticalUpdates' -NotCategory 'Drivers' | `
Out-File "C:\Windows\Logs\WU-$(Get-Date -Format yyyyMMdd-HHmm).log"
Install-WindowsUpdate -MicrosoftUpdate -Category 'SecurityUpdates','CriticalUpdates' `
-NotCategory 'Drivers' -AcceptAll -IgnoreReboot -WhatIf:$false -Verbose
注意:Server 2012 默认 PowerShell 版本较老,建议先上 WMF 5.1,TLS1.2 打开后安装 PSGallery 模块更顺滑。如受限,可把 PSWindowsUpdate 离线拷贝上去导入。
计划任务建议
- 02:55 运行 Check-And-Install-WindowsUpdate.ps1
- 03:30 再次运行(兜底)
- 04:30 检查是否需要重启,按批次重启
5) 重启控序:先摘流,再重启,再拉起
对无状态前端来说,重启不可怕,失控重启才可怕。
IIS 前端批次重启流程
摘流:NGINX/SLB 上把某批机器权重调 0 或移出池;或在本机 netsh http add iplisten 做本地阻断(简化法是 app_offline.htm + 健康探针失败)
安装并重启(或安装后单独判定是否需要重启)
应用预热:IIS Application Initialization 打开,Preload Enabled,预热 URL 成功后再入池
健康检查通过再换下一批
检测是否需要重启:
# 需要重启?
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") -ne $null
6) 安全回滚(必须有)
列出更新包:
dism /Online /Get-Packages /Format:Table | more
卸载指定 KB(静默,无重启):
wusa /uninstall /kb:5034123 /quiet /norestart
重启后验证:再次 dism /Online /Get-Packages,并核查应用日志与合规扫描。
7) 没有 WSUS / 只有“独服几台”的轻量做法
如果短期内没法上 WSUS,至少把下载/安装/重启三件事“掐点”:
- BITS 限速(见第 2 步)
- GPO 设定安装窗口(见第 3 步)
- 任务计划 + 负载脚本(见第 4 步)
- sconfig(Server Core):sconfig → 选择 5) Windows Update → 设为“仅下载,手动安装”或“计划安装 03:00”。
配置清单(一页总览)
GPO 建议矩阵
| 策略项 | 路径 | 推荐值 |
|---|---|---|
| 指定 WSUS | 计算机配置 → 管理模板 → Windows Update | http://wsus-hk-01:8530 |
| 配置自动更新 | 同上 | 4 - 自动下载并按计划安装,03:00 |
| 针对已登录用户不自动重启 | 同上 | 启用(RDS/堡垒机 必须) |
| 自动更新检测频率 | 同上 | 4 小时 |
| 重新计划安装 | 同上 | 启用,15 分钟 |
| BITS 限速 | 计算机配置 → 管理模板 → 网络 → BITS | 白天 1 Mbps;凌晨不限 |
| 自动维护时间 | 注册表 | 03:00 |
批次与窗口
| 组别 | 覆盖比例 | 安装窗口(HKT) | 重启策略 |
|---|---|---|---|
| Ring 0 | 1–2 台 | 周三 02:00–05:00 | 预热后入池 |
| Ring 1 | 20% | 周四 02:00–05:00 | 分批 |
| Ring 2 | 其余 | 周五 02:00–05:00 | 分批 |
真实落地后的对比数据
| 指标 | 优化前 | 优化后(连续 3 周) |
|---|---|---|
| 峰前(18:00–20:00)CPU P95 | 42% | 39% |
| 安装期 CPU P95 | 78%(随机踩到业务) | 47%(固定 02–05 点) |
| 磁盘队列 P95 | 3.1 | 0.9 |
| P95 响应时间 | 600+ ms(抖) | 210–240 ms(稳) |
| 异常重启/周 | 3–5 台 | 0–1 台(多为人工触发) |
线上“坑”与现场解法(都是血泪)
- 时区踩坑:GPO 安装时段按本机时区解释。香港节点请确认 TimeZone = China Standard Time(HKT 同区,不涉夏令时)。
- WSUS 在异地:曾让香港节点跨境拉补丁,带宽打满。解决:在香港建下游 WSUS;或者开分发点/Cache。
- .NET 补丁触发应用池大规模 JIT:导致首波请求慢。解决:IIS Application Initialization+预热线程,在入池前把关键路由跑一遍。
- PSGallery/TLS:Server 2012 老环境装模块报 TLS 错,装 WMF 5.1、启用 TLS 1.2 再走。
- 数据库层别乱动:SQL 节点的系统补丁放单独窗口;先跑可用性组/故障转移演练再装。
- “禁止自动重启”用了个爽:结果长期不重启,堆旧补丁。解决:月度强制维护夜,以批次 drain + 重启收尾。
- 监控误报:凌晨大版本堆积导致磁盘短时突刺,Zabbix 报红。给维护窗挂抑制规则并记录变更号。
附:快速联机与检测命令
# 立即向 WSUS 报到、检查
wuauclt /detectnow
wuauclt /reportnow
# 查看是否有待重启
Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
# 查看被安装/待安装更新(PSWindowsUpdate)
Import-Module PSWindowsUpdate
Get-WindowsUpdate -MicrosoftUpdate
# 仅下载(不装)
Get-WindowsUpdate -Download
# 安装(不重启),只安全/关键更新
Install-WindowsUpdate -MicrosoftUpdate -Category 'SecurityUpdates','CriticalUpdates' -NotCategory 'Drivers' -AcceptAll -IgnoreReboot
政策与版本提醒(务必看)
Windows Server 2012 / 2012 R2 已过主流支持期,如果你在合规环境里运行,请确认是否在 **ESU(扩展安全更新)**或第三方扩展支持计划内。没有支持就别开放公网面。
能迁就迁(我说的是长远计划),但在迁移前这套更新策略能显著降低高峰期被更新拖垮的概率。
写完最后一条计划任务,我在机柜门上敲了两下,当作给它们打个气。凌晨四点,机房风声还是一样,可监控屏幕终于不再像心电图一样颤抖——更新在凌晨安安静静地装好,IIS 应用热起来,健康探针一个个绿回去。第二天晚高峰,客服群里没人再提“偶发卡顿”。
这活儿干完的那一刻,我对“可预期”三个字有了新的敬畏:更新并不可怕,可怕的是它失去边界。把源头、下载、安装、重启四条边界划清,系统就不会在你最需要它的时候掉链子。
清单(拿走就能干)
- 上 WSUS(或下游 WSUS 在香港)
- 只批“安全/关键”分类,分 Ring 批准
- GPO:03:00 HKT 安装;不对登录用户强制重启
- BITS:白天限速,凌晨放开
- 02:55 运行负载检查脚本,负载高则延后
- 批次摘流→安装→预热→入池→下一批
- 回滚脚本 wusa /uninstall /kb:xxxxx /quiet /norestart
- 监控抑制 + 变更登记
如果你现在正坐在香港机房的冷通道里,愿这套做法能让你今晚比我那晚更轻松一点。需要,我也可以把上面的脚本和 GPO 模板再按你的环境改一版。