在我的工作中,我有一个由我负责的六个Windows服务,用C#2003编写。每个服务都包含一个计时器,每分钟都会触发,大部分工作都在这里发生。

我的问题是,当这些服务运行时,它们开始在循环的每次迭代中消耗越来越多的CPU时间,即使它们没有有意义的工作要做(即,它们只是闲置,查看数据库)做某事)。 当它们启动时,每个服务使用4个CPU的平均(约)2-3%,这很好。 24小时后,每个服务将在其循环运行期间消耗整个处理器。

有人可以帮忙吗? 我不知道是什么导致了这一点。 我们当前的解决方案是每天重启服务一次(他们关闭自己,然后脚本看到他们离线并在凌晨3点重新启动它们)。 但这不是一个长期的解决方案; 我担心的是,随着服务变得越来越繁忙,每天重启一次可能还不够......但是因为它们有更大的启动惩罚(它们都使用NHibernate进行数据访问),因为它们变得更加繁忙,正是我们没有想要做的是更频繁地重新启动它们。


@akmad:没错,这很难。

  1. 是的,隔离运行的服务会随着时间的推移显示相同的症状。
  2. 不,它没有。 我们已经看过了。 这可能发生在上午10点或下午6点或半夜。 没有一致性。
  3. 我们的确是; 他们是。 服务正在做他们应该做的事,而不是别的。
  4. 不幸的是,这需要预先知道服务何时将最大化CPU,这发生在一个不可预测的时间表上,而且从来没有很快......这使得事情变得更加困难,因为我的老板会在他们开始拥有时运行并重新启动它们没有考虑调试问题的问题。
  5. 不,他们使用相当一致的RAM(每台大约60-80MB,机器上4GB)。

很好的建议,但请放心,我们已经尝试了所有常见的故障排除。 我希望这是一个有人可能知道的.NET问题,我们可以解决这个问题。 我的老板的解决方案(我强调不想实现)是在数据库中放置一个字段,该字段保存多次,以便服务在白天重新启动,这样他就可以解决问题而不去考虑它。 我正在拼命寻找真正问题的原因,以便我能解决它,因为这个解决方案将在大约六个月内成为灾难。


@Yaakov Ellis:他们每个人都有不同的功能。 一个人从异地的某个地方读取Oracle数据库中的记录; 另一个处理这些记录并将属于这些记录的文件传输到我们的系统; 第三个检查这些文件,以确保它们是我们期望的那样; 另一种是维护服务,它不断检查磁盘空间(我们已经足够)等内容并轮询其他服务器以确保它们存活; 一个正在运行,只是为了确保所有其他正在运行并执行其工作,监视和报告错误,并重新启动任何无法保持整个系统一天24小时运行的事情。

所以,如果你问我认为你在问什么,不,所有这些服务都没有一个共同点(除了通过NHibernate访问数据库),我可以指出这是一个潜在的问题。 不幸的是,如果事实证明这是实际问题(这不会让我感到惊讶),整个事情可能会被搞砸 - 我最终会用简单的SQL重写所有这些问题。 我希望这是一个垃圾收集器问题或者比NHibernate更容易处理的东西。


@Joshdan:不是秘密。 正如我所说,我们已经尝试了所有常见的故障排除。 分析是无益的:我们使用的分析器无法指向CPU使用率很高时实际执行的任何代码。 大约一个月前,这些服务被撕裂,寻找这个问题。 分析了每个代码段,试图弄清楚我们的代码是否是问题; 我不是在这里问,因为我没有完成我的作业。 如果这是服务工作比预期更多的简单案例,那就是本应该被捕获的东西。

这里的问题是,在大多数情况下,服务根本没有做任何事情,但仍然设法消耗四个CPU核心中的25%或更多:他们发现没有工作要做,并退出他们的循环并等待下一次迭代。 从字面上看,这应该几乎不占用CPU时间。

以下是我们所看到的行为示例,该服务在两天内没有工作要做(在不变的环境中)。 这是上周捕获的:

第1天,上午8点:平均 CPU使用率约3%
第1天,下午6点:平均 CPU使用率约8%
第2天,早上7点:平均 CPU使用率约20%
第2天,上午11点:平均 CPU使用率约30%

看了所有可能的世俗原因,我在这里问了这个问题,因为我认为(正确的,事实证明)我会得到更多创新的答案(比如Ubiguchi的),或指向我没有的东西'没有认真(像伊恩的建议)。


那么CPU尖峰是在定时器回调之前,定时器回调中,还是在定时器回调之后立即发生的?

你误会了。 这不是一个尖峰。 如果是的话,就不会有问题; 我可以处理尖峰。 但它不是...... CPU使用率普遍上升。 即使服务无所事事,等待下一次计时器命中。 当服务启动时,事情很好而且平静,图表看起来像你期望的......通常,0%的使用率,当NHibernate点击数据库或服务做了一些微不足道的工作时,峰值达到10% 。 但是在流程运行的过程中,这种情况一直增加到25%(更多,如果我让它走得太远)。

这使得伊恩的建议成为逻辑银弹(当你不看的时候,NHibernate会做很多事情)。 唉,我已经实现了他的解决方案,但它没有产生影响(我没有证据证明这一点,但实际上我认为这会让事情变得更糟......现在平均使用率似乎要快得多)。 请注意,剥离NHibernate“部分”(如您所推荐)是不可行的,因为这将剥离服务中大约90%的代码,这将让我排除计时器作为一个问题(我绝对打算尝试),但不能帮助我排除NHibernate作为问题,因为如果NHibernate导致这个,那么实施的狡猾的修复(见下文)将必须成为系统的工作方式; 我们如此依赖NHibernate进行这个项目,PM根本不会接受它导致无法解决的结构问题。

我只是在问题中注意到一种绝望感 - 你的问题会继续阻止一个小小的奇迹

不要故意让它脱离这种方式。 目前,服务正在每天重新启动(可选择输入一天中的任意小时数来关闭和重启),这可以解决问题,但一旦进入生产机器就不能成为长期解决方案并开始变得忙碌。 问题不会继续,无论我修复它们还是PM都会对它们保持这种约束。 显然,我更愿意实现一个真正的修复,但由于最初的测试显示没有理由,并且服务已经被广泛审查,因此PM宁愿让它们重新启动多次,而不是花费更多的时间来修复它们。 这完全超出了我的控制范围,使你所说的奇迹比其他方式更重要。

这是非常有趣的(只要您信任您的探查器)。

我不。 但是,这些是在Windows 2000机器上运行的Windows服务,由一个狡猾的Nant脚本部署,使用旧版本的NHibernate进行数据库访问。 我真的说我相信那台机器很少。

===============>>#1 票数:3

你提到你正在使用NHibernate - 你是否在适当的时候关闭你的N​​Hibernate会话(例如每次迭代结束?)

如果没有,那么加载到内存中的对象映射的大小将随着时间的推移逐渐增加,并且每次会话刷新将占用越来越多的CPU时间。

===============>>#2 票数:3

这是我开始的地方:

  1. 获取Process Explorer并显示JIT中的%时间,GC中的%时间,CPU周期增量,CPU时间,CPU%和线程。
  2. 你还需要内核和用户时间,以及一些代表性的堆栈跟踪,但我认为你必须点击属性来获取快照。
  3. 拍摄之前和之后比较。

关于可能性的几点想法:

  • 过多的GC(GC中的时间百分比上升。此外,Perfmon GC和CPU计数器将对应)
  • 过多的线程和相关的上下文切换(线程数上升)
  • 轮询(堆栈跟踪始终在单个函数中捕获)
  • 内核时间过长(内核时间很长 - 任务管理器显示CPU高时的大内核时间数)
  • 异常(PE .NET选项卡抛出的异常很高并且越来越高。还有一个Perfmon计数器)
  • virus / rootkit(好吧,这是最后一个漏洞的情况 - 但是有可能构建一个隐藏在TaskManager中的rootkit。我怀疑如果你足够狡猾,你可以将不可避免的CPU使用量分配给另一个进程。此外,如果你已经排除了上述所有内容,我现在就没有想法了)

===============>>#3 票数:2

显然很难远程调试你是未知的应用程序......但这里有一些我要看的东西:

  1. 当您一次只运行其中一项服务时会发生什么? 你还看到减速吗? 这可能表明服务之间存在争议。
  2. 无论服务运行多长时间,问题是否总是在同一时间发生? 这可能表明其他东西(备份,病毒扫描等)导致整个机器(或数据库)变慢。
  3. 您是否有日志记录或其他一些机制来确保该服务仅按您认为的那样经常工作?
  4. 如果您可以在短时间内看到性能下降,请尝试运行该服务一段时间,然后附加一个分析器以查看与CPU挂钩的确切内容。
  5. 你没有提到任何关于内存使用的事情。 你有这些服务的信息吗? 您可能会耗尽大部分RAM并导致磁盘丢失或出现类似问题。

祝你好运!

===============>>#4 票数:2

我建议将这个问题分解成碎片。
首先,找到一种方法,100%的时间和快速重现问题。 降低计时器,以便更频繁地启动服务(例如,比正常情况快10倍)。 如果问题出现的速度要快10倍,那么它与迭代次数有关,而与实时或服务所做的实际工作无关。 而且您将能够比一天更快地完成后续步骤。
其次,注释掉所有实际工作代码,并只让服务,定时器和同步机制。 如果问题仍然出现,那么它将出现在代码的那一部分中。 如果没有,则开始添加您注释掉的代码,一次一个。 最后,您应该找出导致问题的代码部分。

===============>>#5 票数:1

'Fra这个答案只是建议你看一些方向,但是在.NET Windows服务中遇到过类似的问题我有一些想法你可能会觉得有帮助。

我的第一个建议是你的服务可能在处理内存方面或者处理非托管内存的方式上有一些错误。 我最后一次跟踪类似的问题时发现了第三方OSS库,我们使用存储句柄来处理静态内存中的非托管对象。 服务运行的时间越长,处理的服务就越多,这导致进程的CPU性能很快就会下降。 尝试解决此类问题的方法是确保您的服务在计时器调用之间不存储任何内存,尽管如果您的第三方库使用静态内存,您可能需要做一些聪明的事情,例如为计时器调用和沟渠创建应用程序域处理完成后,应用程序doamin(及其静态内存)。

我在类似情况下看到的另一个问题是定时器同步代码是可疑的,这实际上允许多个线程一次运行处理代码。 当我们调试代码时,我们发现第一个线程阻塞了第二个,当第二个线程开始时,第三个线程被阻止了。 随着时间的推移,阻塞持续时间越来越长,因此CPU使用量也越来越高。 我们用来解决问题的解决方案是实现正确的同步代码,因此如果不阻塞,计时器只会启动另一个线程。

希望这会有所帮助,但如果我的想法都是红色的鲱鱼,那么他们会道歉。

===============>>#6 票数:1

听起来像计时器的线程问题。 您可能有一个工作单元阻止另一个工作在不同的工作线程上运行,导致它们在每次计时器触发时都会堆叠起来。 或者你可能有比你想象的更长的生存和工作时间。

我建议重构计时器。 将其替换为在ThreadPool上排队工作的单个线程。 您可以Sleep()线程来控制查找新工作的频率。 确保这是代码多线程的唯一位置。 所有其他对象应该被实例化,因为工作准备好进行处理并在完成工作后销毁。 状态是多线程代码中的敌人。

设计缺乏的另一个领域似乎是您有多个服务轮询资源来执行某些操作。 我建议在一项服务下统一它们。 他们可能分开做事,但他们齐心协力; 你只是使用文件系统,数据库等作为方法调用的替代。 还有,2003年? 我为你感到伤心。

===============>>#7 票数:0

很好的建议,但请放心,我们已经尝试了所有常见的故障排除。 我希望这是一个有人可能知道的.NET问题,我们可以解决这个问题。

我的感觉是,无论底层原因多么奇怪,通常的故障排除步骤都是找到问题的最佳选择。

由于这是一个性能问题,良好的测量是非常宝贵的。 整个过程CPU的使用范围太广了。 您的服务在哪里花费时间? 您可以使用分析器来测量它,或者只记录各个部分的开始和停止。 如果您无法做到这一点,那么请使用Andrea Bertani的建议 - 通过删除其他部分来隔离部分。

一旦找到了常规区域,就可以进行更细粒度的测量,直到找出CPU使用情况的来源。 如果在那一点上如何解决它并不明显,那么你至少需要弹药来解决更具体的问题。

如果您事实上已经完成了所有这些常见的故障排除,请让我们知道这个秘密。

  ask by TheSmurf translate from so

未解决问题?本站智能推荐:

6回复

找出Windows服务的运行进程名称.NET 1.1

我们正在使用一个写得很糟糕的Windows服务,当我们尝试从代码中阻止它时,它将挂起。 因此,我们需要找到与该服务相关的进程并将其终止。 有什么建议?
1回复

Windows服务+ Nhibernate-尖锐的体系结构-内存泄漏? [关闭]

我有一个Windows服务,该服务执行由时间触发的批量插入。 我正在使用夏普(contrib)体系结构和NHibernate。 服务的内存消耗似乎随时间缓慢/线性增加。 我想调查是什么原因造成的。 有人能这么善良地推荐工具吗? 谢谢。
2回复

在多线程Windows服务应用程序中使用的最佳NHibernate会话管理方法是什么?

我有一个使用多线程的Windows服务应用程序。 我在这个应用程序的数据访问层使用NHibernate。 您对此应用程序中的会话管理有何建议? 我读到了UNHAddins,这是一个很好的解决方案吗?
1回复

如何使用nhibernate和多个存储库执行数据库查询(在窗口服务下)

我知道这个问题问了很多(我认为),但是我在最聪明的程序员(谷歌)中找不到明确的答案。 我已经实现了一些存储库(不是通用存储库),但是实现了每个实体。 我应该使用工作单位模式吗? 那里有很多数据和信息,但不能将我的手指放在“正确的”解决方案上,还是根本不是一个好的解决方案?
1回复

将旧的.Net 1.1 Windows Service升级到3.5,我需要卸载/重新安装吗?

我已将解决方案从.Net 1.1升级到Visual Studio中的.Net 3.5,并且可以重新编译而没有错误。 Windows Server 2008 R2已经安装了旧的1.1 Windows服务。 我需要完全卸载旧服务,还是可以只覆盖新文件? 所有旧应用升级到3.5后,我们将从服务器
1回复

Windows服务增加了高CPU使用率

我创建了一个Windows服务 ,该服务会将数据从生物识别技术保存到数据库。 我使用Mysql作为数据库,然后使用ZKTeco作为Biometrics 。 为了从生物识别技术中获取数据,我使用了dll 。 但是,主要问题是该服务将其高CPU使用率从0.01%增加到30-50%并且不会下
2回复

在C#.NET 1.1中限制股票行情指示器中的CPU使用率

我使用System.Threading.Thread在C#.NET 1.1中创建了一个股票行情指示器组件(System.Windows.Forms.UserControl)。 此行情记录器将从右向左滚动,并从xml feed中读取数据。 我们的主应用程序将在视频和其他进程运行时调用此组件。
1回复

Windows服务和Nhibernate

我有一个带有计时器的Windows服务,并且在timer_Elapsed事件处理程序中将调用另一个组件的方法,该方法应该调查db并获取或更新一些记录。此过程每2分钟发生一次。我使用nhibernate来获取数据组件中的访问。 当我从单元测试运行该方法时,它工作正常,这意味着配置和映射是正确的,
4回复

正确将Windows Forms Datagrid绑定到数组

我正在尝试使用Windows窗体datagrid(.NET 1.1)更新二维数组的元素。 使用Microsoft文档,我已经能够获得datagrid来正确显示阵列。 编辑:我遵循的MS指令位于http://support.microsoft.com/kb/315786 。 我还将
1回复

Windows 10 Creator中的1.1 Framework程序未捕获NullReferenceException

我想知道是否有人在装有Windows 10 Creator的计算机上安装了Dotnet Framework 1.1的人能为我做一点测试。 似乎以下代码片段(错误地)产生了StackOverflow异常并崩溃。 您不需要安装Visual Studio,最简单的编译方法是将其保存到文件