Windows Server 2003 上句柄“泄漏”

本文通过重现句柄线性增长的问题并深入分析,发现所谓的“泄漏”其实是CriticalSection内部的event同步对象延迟创建机制所致。文章详细记录了问题的发现、定位及最终解决方案。
部署运行你感兴趣的模型镜像

现象是在soak测试场景中,每天以线性关系增长700个句柄。

 
解决过程如下:
  1. 重现问题。只要问题能稳定重现,那就很容易解决。这次很幸运,很轻松弄好了重现环境。
  2. 使用windbg attach到被调试进程。
  3. 启用操作系统对于句柄栈追踪功能:!htrace -enable。
  4. 等问题重现以后,使用!htrace -diff来看这两个命令之间所有打开了但还没有被关闭的句柄。
结果令我吃了一惊,从堆栈显示,“泄漏”竟然指向EnterCriticalSection(),这是系统提供的函数,应该不会出错,所以可能是符号表没有正确加载,从而导致堆栈不正确。于是我重新加载应用程序和系统的符号表,再次测试,结果还是一样。于是我突然意识到所谓的“泄漏”可能是虚惊一场,句柄增长的真正原因是CS内部使用的event同步对象延迟创建机制导致的。即每个CS只有在真正有多线程竞争它的时候才初始化内部的内核对象,完成同步工作。
 
于是经过和测试人员沟通,发现问题场景确实是不断会竞争CS,从而导致event对象不断创建,而且竞争的数量分布也很均匀,符合句柄现行增长的现象。所以问题分析结束。

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### Windows Server Handle Count Exceeds 100,000: Causes and Troubleshooting 在Windows服务器上,句柄(Handle)是操作系统用来管理资源的一种机制,包括文件、注册表项、线程、进程、网络连接等。当系统中打开的句柄数量超过正常范围(例如超过100,000)时,可能会导致性能下降甚至系统不稳定。以下是可能导致句柄数过高的常见原因及相应的排查和解决方法。 #### 常见原因分析 1. **应用程序泄漏** - 某些应用程序可能未能正确释放已打开的句柄,导致句柄持续增长。这种问题通常出现在长期运行的服务或第三方软件中。 - 可通过性能监视器(PerfMon)中的 `Process` 对象下的 `Handle Count` 计数器来监控特定进程的句柄使用情况。 2. **服务或驱动程序问题** - 系统服务或设备驱动程序也可能存在句柄泄漏问题,尤其是在未正确关闭资源的情况下。 - 使用 `handle.exe` 工具(来自 Sysinternals)可以查看哪些进程打开了大量句柄,并进一步分析其类型和来源。 3. **数据库引擎行为** - SQL Server 等数据库系统在高并发场景下会创建大量内部对象(如游标、临时表、锁等),这些对象可能占用大量句柄。 - 特别是在某些版本中,SQL Server 使用的 SQLOS 子系统可能会因定时器粒度设置为 1ms 而增加资源消耗 [^1]。 4. **多线程应用不当管理线程资源** - 多线程应用程序如果频繁创建和销毁线程而没有正确释放相关资源,也会导致句柄堆积。 5. **远程调用或网络连接未释放** - 如果服务器作为客户端频繁发起远程调用(如 RPC、WCF、HTTP 请求),而未能正确关闭连接,也可能导致句柄数上升。 --- ### 故障排查步骤 #### 1. 使用任务管理器初步查看 - 打开任务管理器(Ctrl+Shift+Esc),切换到“性能”选项卡,查看当前系统的“句柄数”是否异常。 - 切换到“进程”选项卡,按“句柄数”排序,找出占用句柄最多的进程。 #### 2. 使用 Process Explorer 查看详细句柄信息 - 下载并运行 [Process Explorer](https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)。 - 双击目标进程,进入“Handles”标签页,查看该进程打开的所有句柄及其类型。 - 可以搜索特定类型的句柄(如 `File`, `Event`, `Mutant` 等),帮助定位泄漏源。 #### 3. 使用 `handle.exe` 命令行工具 - 下载 [Handle](https://docs.microsoft.com/en-us/sysinternals/downloads/handle) 工具。 - 运行以下命令查找包含特定字符串的句柄: ```cmd handle.exe <PID> ``` - 或者查找所有包含某个关键词的句柄(如文件路径、事件名称): ```cmd handle.exe \Device\HarddiskVolume ``` #### 4. 使用性能监视器(PerfMon) - 添加计数器:`Process` -> `Handle Count`,选择可疑进程进行实时监控。 - 同时可以添加 `Memory` -> `Pool Paged Bytes` 和 `Pool Nonpaged Bytes` 来观察内核池内存使用情况。 #### 5. 使用 WMI 查询句柄信息 - 使用 PowerShell 查询指定进程的句柄数: ```powershell Get-WmiObject Win32_Process -Filter "ProcessId = <PID>" | Select HandleCount ``` #### 6. 分析日志与事件查看器 - 检查系统日志(Event Viewer)中是否有与句柄耗尽相关的错误或警告信息。 - 关注 `System` 日志中是否有 `Event ID 6008`(事件日志服务启动失败)、`Event ID 4103`(资源不足)等。 #### 7. 内存转储分析(高级) - 若无法通过常规手段定位问题,可使用 `procdump.exe` 生成内存转储文件: ```cmd procdump.exe -ma <PID> dump.dmp ``` - 使用 WinDbg 分析转储文件,查找句柄泄漏的具体位置。 --- ### 解决方案建议 1. **更新或修复应用程序** - 确保所有运行的应用程序和服务都是最新版本,尤其是第三方软件,可能存在已知的句柄泄漏问题。 2. **重启服务或系统** - 对于临时性问题,重启相关服务或整个系统可以快速释放被占用的句柄。 3. **优化数据库配置** - 对于 SQL Server,检查是否存在过多游标版本(Cursor Version Counts)问题 [^2]。 - 优化查询以减少临时对象的创建,避免不必要的连接和事务。 4. **限制最大句柄数(不推荐)** - 虽然可以通过修改注册表限制每个进程的最大句柄数,但这不是根本解决办法,且可能导致应用程序崩溃。 5. **启用跟踪标志(Trace Flag)辅助诊断** - 在 SQL Server 中,可以启用特定的跟踪标志(如 TF 8038)来避免某些系统行为对 DMV 输出的影响 [^1]。 6. **定期监控与自动化脚本** - 使用 PowerShell 或其他脚本语言编写监控脚本,定期记录句柄数变化趋势,及时预警。 --- ###
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值