【问题标题】:100 % CPU by IIS process by Service Model-4 module after the wcf request has passed通过 wcf 请求后,服务模型 4 模块的 IIS 进程 100 % CPU
【发布时间】:2017-05-25 06:27:49
【问题描述】:

我有一个问题,我正在努力争取一个星期。我有一个在 Windows Server 2012 R2 上的 IIS 8.5 中运行的 WCF 服务和一个每 30 秒发出一个或两个请求的 Windows 服务客户端。在某个时间点(通常在服务运行的两个小时内),其中一个请求导致服务应用程序池(与其他应用程序池分离)进程获得 CPU 使用率。在 IIS 工作进程部分可以看到,这个请求永远不会结束,并且在 AuthenticateRequest 状态下挂在 ServiceModel-4 模块中(即很可能它在某处处于无限循环中)。在某个时候,另一个这样的请求被添加到第一个请求中,直到它们变成四个,永远保持并导致 100% 的 CPU 使用率(机器上有 4 个逻辑处理器)。我所做的调查,解决了这个问题:

  • 使用 wcf 跟踪和自定义日志记录来确定问题所在。 Wcf 跟踪实际上显示向服务器发出的所有请求以毫秒 (!) 为单位成功传递(同时客户端的 wcf 跟踪当然显示相同请求的超时)。自定义日志记录还显示服务代码正在调用请求操作的返回。该方法的结果是两个简单的 dto 对象,因此没有可能的序列化问题,也没有在从服务发送回复之前正在执行的端点行为或任何自定义代码(除了方法代码,正如我提到的那样成功返回) .

  • 使用了 iis 失败的请求跟踪,它显示请求到达 ServiceModel-4 而没有继续使用以下信息: 模块名称:ServiceModel-4.0 通知:AUTHENTICATE_REQUEST Http状态:500 HttpReason:内部服务器错误 HttpSubStatus: 0 ErrorCode:操作成功完成(0x0)

  • 使用 Debug Diag 跟踪持续超过 10 分钟的请求,并查看运行时间长的线程。堆栈跟踪如下:

或如下:

我已经看到这些是从 iis 进程中调用的。由于这些是 .Net 功能,我怀疑首先损坏了 .Net 安装,而且服务器上同时安装了 .Net4.5 和 .Net4 (我不知道这到底是怎么发生的)。所以:

  • 我卸载了 .Net4 和打开/关闭 Windows 功能我关闭了 .Net4.5 功能,重新启动,然后我打开它们,重新启动,但没有成功

  • 之后,我以同样的方式重新安装了 IIS(来自 Windows 功能)。再次没有成功。

没有更多的想法。

【问题讨论】:

  • 你有没有在托管代码内部运行的多线程代码,它可以抽出CPU,并可能进入无限循环,没有可用的出口,从而无限消耗资源。我建议使用 Dot Trace 分析器并检查执行过程中有哪些方法,它比其他 Windows 调试工具更具描述性。

标签: c# wcf iis


【解决方案1】:

似乎我找到了答案(但没有使用 Dot Trace 或其他工具)。可以从多个线程访问通用字典。这似乎是一个已知问题:

https://blogs.msdn.microsoft.com/tess/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary/

https://blogs.msdn.microsoft.com/asiatech/2009/05/11/asp-net-application-100-cpu-caused-by-system-collections-generic-dictionary/

其实我在研究之初就注意到了这个问题但是排除了,因为我无法重现它(可能是因为我没有在iis app中测试字典,当然我收到了各种异常,但不是100 % Cpu),主要是因为所有日志都显示访问字典的代码已经通过,而且上面的堆栈跟踪与字典无关。

但是我认为问题发生在解释记录信息的字典(这是数据合同)的序列化过程中。 仍然无法解释这到底是如何发生的。如果有人能解释一下,我想这对每个人来说都是一个很好的知识。

【讨论】:

  • 您好,一般来说,使用通用字典作为数据契约是没有问题的,只要它以线程安全的方式在代码中读取和写入即可。这当然适用于通用字典的所有用例场景,但问题在“数据契约”场景中非常“隐藏”,因为它发生在字典序列化期间,在自定义应用程序代码已经完成之后字典的所有操作。
  • 另一方面,在我看来,使用字典作为数据契约并不是一个好习惯,因为:1) 字典是 .NET 的东西,可能无法很好地支持不同于 .NET您服务的客户。 2) 字典不可扩展 - 如果您使用简单类型作为键值,并且在某些时候您需要为此添加更多信息,您必须更改数据协定,而不是仅仅对其进行非破坏性扩展。
  • 因此,我建议只使用自定义对象而不是字典作为数据协定。如果需要,您仍然可以出于性能原因在代码中使用字典(如果您对它具有多线程访问权限,还可以使用 ConcurrentDictionary)并在最后将其转换为自定义对象作为数据协定
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多