服务假死排查是什么
假死的典型特征:服务进程还在、SCM 显示 Running,但请求得不到响应,重启一次就恢复,过一阵又犯。这类问题通常不在服务本身,而在线程池耗尽、死锁、或依赖后端超时把工作线程占满。排查的目标不是尽快重启,而是在重启前把现场留住,否则同一个故障会反复来。
基本信息
| 现象特征 | SCM 状态为 Running 但功能无响应 |
|---|---|
| 第一判据 | 状态查询正常、端口测试或应用请求超时 |
| 常见根因 | 死锁、线程池耗尽、依赖后端不可达导致调用堆积 |
| 现场保留 | 进程 dump、句柄数、线程状态、应用日志最后时间点 |
| 常用命令 | sc query、Test-NetConnection、Get-Process、Get-Counter |
排查顺序
- 确认服务状态:sc query 看是否为 Running,排除“进程在但已退出”
- 验证端口与业务口:Test-NetConnection 测监听是否还能建连
- 量资源:Get-Process 看 CPU、句柄数、工作集是否异常增长
- 看线程与连接:确认线程数与已建立连接是否顶到上限
- 查日志时间戳:应用日志与事件日志最后一条活动时间是否断档
- 抓现场:资源与日志都指向卡死后,先做 dump 再重启
常用示例
常用示例
sc query MySvc | Select-String 'STATE' # 看服务状态
Test-NetConnection 127.0.0.1 -Port 8080 # 端口还能不能建连
Get-Process -Name MySvc | Select-Object Id, CPU, Handles, WorkingSet64, Threads.Count # 资源与线程
Get-Counter '\Process(MySvc)\Thread Count' -SampleInterval 2 -MaxSamples 5 # 线程数随时间变化
Get-WinEvent -FilterHashtable @{LogName='Application'; StartTime=(Get-Date).AddHours(-2)} -MaxEvents 30 | Where-Object ProviderName -like '*MySvc*' # 最近应用日志
Get-NetTCPConnection -OwningProcess (Get-Process MySvc).Id | Group-Object State # 连接状态分布指标与判读
| 指标 | 正常表现 | 异常含义 |
|---|---|---|
| CPU 占用 | 随业务波动 | 持续 0 且请求超时=阻塞在等待 |
| 句柄数 | 平稳或缓慢增长 | 快速上涨多为句柄泄漏 |
| 线程数 | 稳定在有限区间 | 顶到池上限说明工作线程被耗尽 |
| 连接数 | 随并发起落 | 大量 Established 不释放提示下游超时 |
| 日志时间 | 持续有新记录 | 停在某时刻说明处理链路卡住 |
抓 dump 的价值在于能看清每个线程卡在哪一行代码:常见是等锁、等数据库连接、等下一条异步回调。没有 dump,事后只能靠猜。
做进程 dump 会短暂冻结目标进程(尤其大内存进程可能停顿数秒到数十秒),生产业务上要评估影响并在变更流程内执行。