Windows服务器如何查看CPU、内存和磁盘使用率?

服务器"卡"了,第一反应不能是重启,而是先看清楚是哪一项资源在瓶颈上:CPU 跑满了要查进程或算法,内存吃紧要看是不是数据库缓存没限制,磁盘 IO 打满往往是慢查询或备份任务引起的。三者的判断标准、处理手段完全不同,看错了方向只会越优化越糟。

这篇讲四条查看路线:任务管理器适合快速扫一眼,资源监视器用来定位具体进程和行为,性能监视器用于长期采样和出图;命令行则用 Get-Counter、typeperf 覆盖 Server Core 与脚本化场景。最后一个重点是 Windows 特有的内存表现——"内存占用高但其实没问题",这个误会每年都能让不少人白白加内存。

任务管理器:三秒快速判断

图形环境下最快的方式。Ctrl + Shift + Esc 直接打开,或 taskmgr.exe,也可以用命令行唤起:

taskmgr
resmon          # 资源监视器,从任务管理器"性能"页左下角也能进入
perfmon         # 性能监视器

Windows Server 2012 之后的任务管理器,"进程"页默认按应用分组显示。要点:

页签 看什么 判断依据
性能 → CPU 总体利用率曲线、逻辑处理器数量 持续 >80% 需要查;偶尔尖峰正常
性能 → 内存 已用/已提交、可用、缓存 重点看可用,不是"已用"
性能 → 磁盘 活动时间百分比、读写速度 活动时间持续 100% 说明 IO 瓶颈
进程 → CPU/内存 按列排序找占用最高的进程 右键"转到详细信息"看具体进程名
详细信息 PID、命令行、用户名 右键可结束进程,谨慎操作

一个实用技巧:任务管理器 → 性能 → 右键图表 → "将图形更改为" → "逻辑处理器",可以看到每个核心的负载曲线,发现单线程程序吃死一个核的情况。

内存这块要看"详细信息"页右键添加列:在列选择器里勾选"提交大小"、"工作集(内存)"、"专用工作集"。专用工作集才是进程真正独占、无法被换页的部分,而"工作集"包含了共享内存,容易被重复计算。

tasklist /fi "memusage gt 40960" /fo table     :: 内存占用超 40 MB 的进程
tasklist /fi "imagename eq w3wp.exe"
tasklist /svc                                   :: 查看每个进程承载的服务

资源监视器:定位"谁在读写什么"

资源监视器 resmon.exe 是任务管理器的增强版,真正做到定位级别的信息都在里面。它有五个页:概述、CPU、内存、磁盘、网络。

值得关注的几个视图:

  • CPU 页:进程列表带"平均 CPU",勾选进程后可以过滤下面的"服务"和"关联的句柄",能看到某个服务占用多少。
  • 内存页:中间那条"已提交内存"进度条是关键,接近物理内存 + 页面文件总量时系统会开始提示虚拟内存不足。
  • 磁盘页:磁盘活动列表按"总计 (B/秒)"排序,能直接看到哪个进程在读哪个文件。磁盘队列长度(Queue Length)持续大于 2 说明 IO 排队。
  • 网络页:进程级的 TCP 连接,能看到每个进程的发送/接收速率,排查异常流量很好用。
resmon
perfmon /res          # 直接打开资源监视器

举个例子:磁盘页显示 MsMpEng.exe(Windows Defender 的进程)持续占 100%,那大概率是定时扫描赶上业务高峰,应该改扫描计划或加排除项,而不是去怪应用软件。

性能监视器与关键计数器

性能监视器 perfmon.exe 是 Windows 上做长期监控的主力。它可以实时也可以把数据存成计数器日志(.blg),事后用同一工具打开分析。

必记的几个计数器:

计数器 采集对象 参考阈值(经验值)
Processor(_Total)\% Processor Time CPU 总利用率 持续 >80% 需关注,>90% 为瓶颈
Processor(_Total)\% Privileged Time 内核态占比 >30% 可能是驱动或系统调用过多
System\Processor Queue Length 处理器队列 每核 >2 说明 CPU 不够用
Memory\Available MBytes 可用物理内存 <总内存 10% 或 <500 MB 告警
Memory\Pages/sec 换页速率 持续 >1000 可能存在内存瓶颈
Memory\Committed Bytes 已提交内存 接近提交限制时需扩容
PhysicalDisk(_Total)\% Disk Time 磁盘忙时占比 持续 >90% 表明 IO 饱和
PhysicalDisk(_Total)\Avg. Disk Queue Length 平均队列长度 每盘 >2 需排查
LogicalDisk(C:)\% Free Space 逻辑盘剩余空间百分比 <10% 应清理或扩容
Network Interface(*)\Bytes Total/sec 网卡吞吐 与带宽上限对比判断跑满与否

注意:% Disk Time 在部分环境下可能超过 100% 或不准确,多盘环境下更可靠的是 Avg. Disk sec/Read、Avg. Disk sec/Write(延迟)。机械盘随机读写超过 20 ms、SSD 超过 5 ms,就说明下面撑不住了。

用 PowerShell 直接读这些计数器,无需打开 GUI:

# 一次性采样:CPU、可用内存
Get-Counter '\Processor(_Total)\% Processor Time'
Get-Counter '\Memory\Available MBytes'
Get-Counter '\LogicalDisk(C:)\% Free Space'

# 连续采样 10 次,每秒 1 次
Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 10

# 一次读多个计数器
Get-Counter -Counter @(
  '\Processor(_Total)\% Processor Time',
  '\Memory\Available MBytes',
  '\PhysicalDisk(_Total)\% Disk Time',
  '\LogicalDisk(C:)\% Free Space'
)

# 取 CPU Top5 进程(注意 cchar 单位)
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name,Id,CPU,WS

可以看到,要什么关键指标就用路径拼出来。中文系统的计数器名也支持本地化写法,但在脚本里建议用英文路径,避免跨语言环境失效。

typeperf 是 CMD 时代的同类工具,写批处理更简单:

typeperf "\Processor(_Total)\%% Processor Time" -si 1 -sc 10
typeperf "\Memory\Available MBytes" -si 5 -sc 12
typeperf -cf counters.txt -o result.csv -f CSV -si 10 -sc 360      :: 每 10 秒一次,采样一小时存 CSV
:: 注意:批处理文件中 % 必须写成 %%,命令行里直接写单个 % 即可

磁盘健康也可以同时看一下,特别是 SSD 的剩余寿命和物理磁盘状态:

Get-PhysicalDisk | Select-Object FriendlyName, MediaType, HealthStatus, Size, Wear
Get-Volume | Select-Object DriveLetter, FileSystemLabel, Size, SizeRemaining, HealthStatus
Get-VirtualDisk | Select-Object FriendlyName, HealthStatus
Get-StorageReliabilityCounter -PhysicalDisk (Get-PhysicalDisk | Select-Object -First 1) | Format-List *

SizeRemaining 除以 Size 就是剩余百分比,脚本里经常用到这个算式做自动告警。

Windows 内存为什么总是"看起来很高"

Windows 的内存表现极易被误判。打开任务管理器看到"已用 85%",大多数人第一反应是"内存不够了,加内存"。实际上绝大多数情况下这些内存是可释放的缓存。

关键在于 Windows 的内存管理哲学是用满为止:空闲内存是浪费,系统会主动把磁盘数据缓存到内存里(Standby List 备用列表),并保留已释放但内容还在的页面以便快速复用。这部分内存在应用程序需要时会被立刻交还。

概念 含义 是否算"真占用"
Working Set(工作集) 进程当前在物理内存中的页 部分可换页
Private Working Set(专用工作集) 进程独占、不能共享的部分 最接近真正的进程占用
Commit(提交大小) 进程申请的虚拟内存承诺 申请不等于使用
Standby / Modified(备用/已修改) 文件缓存 否,可被立刻回收
Available(可用) 可分配给新进程的内存 判断可用性的唯一标准

判断内存是否真的紧张的唯一标准是 Memory\Available MBytes,而不是"已用百分比"。可用内存低于物理内存 10% 、或者低于 500 MB 到 1 GB(视总量而定),同时 Pages/sec 长期在高位,才是真正的内存瓶颈。

要查看更精确的列表,可以用RAMMap(Sysinternals 工具)或 PowerShell 的输出:

# 总的提交/物理内存概况
Get-CimInstance Win32_OperatingSystem |
  Select-Object TotalVisibleMemorySize, FreePhysicalMemory, TotalVirtualMemorySize, FreeVirtualMemory |
  Format-List *

# 换算成 GB
$os = Get-CimInstance Win32_OperatingSystem
[math]::Round($os.TotalVisibleMemorySize/1MB,2)
[math]::Round($os.FreePhysicalMemory/1MB,2)

# 页面文件大小与位置
Get-CimInstance Win32_PageFileUsage | Select-Object Name, AllocatedBaseSize, CurrentUsage

SQL Server 是典型的"看起来占满"的程序。它默认会根据可用内存增长缓冲区,只增不减,最后把内存全吃掉。这不是故障,但会影响同一台机器上的其他服务,解决办法是给 max server memory 设上限(比如物理内存的 70%-80%),而不是不管它或者反过来给它加更大的机器。

命令行全景:进程与端口一起看

真正查性能问题时,通常是"看进程 → 看它的 IO → 看它的网络连接"三步连起来做:

# CPU 占用 Top 10,并把工作时间折算成 MB
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 `
  Name, Id, @{n='CPU(s)';e={[math]::Round($_.CPU,1)}}, @{n='MemMB';e={[math]::Round($_.WorkingSet64/1MB,1)}}

# 查看某进程的总连接数(判断连接泄漏)
Get-NetTCPConnection | Group-Object State | Select-Object Name, Count
Get-NetTCPConnection -State Established | Group-Object OwningProcess | Sort-Object Count -Descending | Select-Object -First 5

# 揪出某个 PID 对应的进程名
Get-Process -Id (Get-NetTCPConnection -LocalPort 80 -State Listen).OwningProcess

Server Core 环境下没有 taskmgr,以上命令就成了唯一的手段。建议把常用的检查脚本封装成一个 ps1 放 C:\Scripts\health.ps1,便于日常巡检。

常见问题

Q:可用内存几乎为零,要不要马上加内存?
先看 Memory\Available MBytes 与 Pages/sec。如果 Available 低但 Pages/sec 也很低(几十以下),说明内存只是被拿去做文件缓存了,属于正常现象。如果 Available 低且 Pages/sec 长期上千,才是真紧张。

Q:% Disk Time 一直是 100%,但读写速度不高?
多见于虚拟化环境或存在 IO 排队的情况。建议同时看 Avg. Disk sec/Read 和 Avg. Disk sec/Write 判断延迟——机械盘 >20 ms、SSD >5 ms 就算慢。也可能是阵列降级(RAID rebuild 中),用 Get-PhysicalDisk 看 HealthStatus。

Q:CPU 占用不高但系统很卡?
可能是 CPU 在等待 IO(% Processor Time 分成用户态/内核态,内核态高说明系统调用或驱动有问题),或者磁盘 IO 已满。看 Processor Queue Length 和 Avg. Disk Queue Length 两个队列类指标。

Q:怎么记录一段时间的性能数据,事后分析?
perfmon.exe → 数据收集器集 → 用户定义 → 新建,添加计数器、设采样间隔(如 60 秒)和日志格式。也可以用 typeperf -cf 存 CSV。生产环境建议采样间隔不低于 15 秒,否则数据量太大。

Q:服务器虚拟内存(页面文件)要不要设?
不建议设为 0。缺少页面文件会导致某些内存转储失败、程序启动报错。一般做法是由系统托管,或设为物理内存的 1.5 倍左右;内存超过 32 GB 时可以固定给 8-16 GB,够系统写 dump 用即可。

总结

  • 判断 CPU 看 Processor(_Total)\% Processor Time 与 Processor Queue Length(每核 >2 才有意义),偶尔尖峰不算故障。
  • 判断内存只看 Memory\Available MBytes,配合 Pages/sec;Windows 内存占用高大多是文件缓存,属于正常。
  • 磁盘除了看 % Disk Time,更要看 Avg. Disk sec/Read(Write) 延迟和队列长度,虚拟化环境下前者常常失真。
  • Server Core 或批量运维用 Get-Counter 和 typeperf,把常用检查脚本固化下来比每次手敲更可靠。
  • 三类指标的习惯配置:% Free Space 低于 10% 要处理、可用内存长期低于 10% 要排查、CPU 持续高于 80% 要定位,这些都是经验参考值,具体还要结合业务峰值来判断。