服务器"卡"了,第一反应不能是重启,而是先看清楚是哪一项资源在瓶颈上: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% 要定位,这些都是经验参考值,具体还要结合业务峰值来判断。
企业QQ咨询




