我有一个ASP.NET应用程序,它通过创建和写入自定义性能计数器来跟踪统计数据。有时,我会在错误日志中看到,计数器无法打开,因为它们已在当前进程中使用。我认为这是由于我的.NET应用程序域已在同一个w3wp.exe进程中重置。当我的应用程序域已回收时,如何避免这些错误并重新建立与性能计数器的连接?
柜台结构:
PerformanceCounter pc = new PerformanceCounter();
pc.CategoryName = category_name;
pc.CounterName = counter_name;
pc.ReadOnly = false;
pc.InstanceLifetime =
PerformanceCounterInstanceLifetime.Process;
pc.InstanceName = instance_name;
柜台使用:
pc.Increment()
[2009年3月26日更新]收到的错误消息是:
示例“_lm_w3svc_1_root_myapp”已存在,生存期为Process。在删除它或使用它的进程退出之前,不能重新创建或重用它。已经存在,其生命周期为Process。
我尝试在控制台应用程序中复制该异常,方法是初始化性能计数器并在一个 transient AppDomain中写入其中一个计数器。然后卸载AppDomain并在第二个Appdomain中再次执行此操作(相同的进程)。他们都成功了。我现在不确定到底是什么原因造成的,我关于AppDomain在ASP.NET中回收的假设似乎是错误的。
6条答案
按热度按时间wqlqzqxt1#
使用process based WCF performance counters时,在应用程序中也可能遇到上述错误。此问题的症状是应用程序事件日志中出现三个错误:
未加载性能计数器。
分类名称:3.0.0.0
柜台名称:电话
异常:System.InvalidOperationException:示例'abc@def| service.svc“已存在,生存期为Process。在删除它或使用它的进程退出之前,不能重新创建或重用它。
此操作总是在系统事件日志中的以下信息消息之后立即发生:
为应用程序池“MyAppPool”提供服务的进程ID为“nnnn”的辅助进程已请求回收,因为该辅助进程已达到其允许的处理时间限制。
这将导致此服务的性能监视器计数器在几个小时内不可用。
ServiceModelService 3.0.0.0
版本号将是depend on the version of .NET you are using(这是使用.NET 3.5测试的)。背景
该错误由工作进程达到其处理时间限制触发,此时必须回收该工作进程。这是在IIS应用程序池回收设置中设置的(IIS 6.0及更高版本,因此是Windows Server 2003及更高版本)。回收辅助进程会导致新的基于进程的性能计数器名称与旧的冲突,从而产生错误。这是因为IIS使用overlapped recycling,其中要终止的工作进程保持运行,直到新的工作进程启动。
复制
<system.serviceModel>
部分中的web.config
:<diagnostics performanceCounters="All" />
W3SVC
信息事件的事件查看器系统日志中所示)。System.ServiceModel 3.0.0.0
的应用程序日志中产生一批三个错误。可能的解决方案
解决方案1 -红鲱鱼
热修复KB981574取代热修复KB971601。后一个修复程序描述了该问题:
FIX:当应用程序退出并重新启动时,监视应用程序的性能计数器停止响应,并且您在运行.NET Framework 2.0的计算机上收到System.InvalidOperationException异常
应用前一个修复程序不能解决问题。应用后一个修复程序导致应用程序池错误。
方案2 -工作方案
可以创建service host factory that exposes a custom service host:
并参考服务标记
.svc
文件中的工厂:<%@ ServiceHost Language="C#" Debug="true" Factory="MyNamespace.WebFarmServiceHostFactory" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" %>
最终调整
不幸的是,尽管这使得问题发生的频率降低了很多,但它仍然会发生(大约少了30倍,尽管我没有测量到准确的统计数据)。
一个简单的调整似乎可以完全解决这个问题,就是在
base.ApplyConfiguration();
之前添加一个sleep命令:这在每个工作进程回收时只触发一次,因此对服务性能的影响可以忽略不计。您可能必须提高此值(您可以使其可配置),尽管最小设置为1 ms对我有效(关于此命令实际休眠多长时间的争论放在一边)。
解决方案3 -最简单的修复
在IIS中有一个
DisallowOverlappingRotation
Metabase Property。此can be set as follows(针对MyAppPool
应用程序池给出的示例):解决方案对比
解决方案#3将cause your site to be down longer时,工作进程由于缺乏IIS重叠回收而重新启动。
在soapUI负载测试中,一个基本的Web服务每秒使用5个线程处理100多个事务,每次工作进程回收时,都会出现几秒钟的“冻结”,即新事务被阻塞。当测试更复杂的Web服务时,冻结时间更长(8秒以上)。
解决方案#2没有产生这种阻塞,在回收期间具有平滑的响应流,并且没有产生性能冲突错误。
结论
对于不要求低延迟的Web服务,可以使用解决方案#3。如果你知道负载分布和一天中的安静时间,你甚至可以将回收设置为每天在一个设定的时间进行(这可以在IIS的同一个选项卡中完成)。如果使用网络农场,这甚至可以错开。
对于不能容忍这种延迟的Web服务,解决方案2似乎是最好的方法。
4sup72z82#
IIRC,IIS不会确保在启动第二个AppDomain之前关闭第一个AppDomain,特别是当您手动或自动回收它时。我相信,当启动回收时,第二个AppDomain首先被示例化,一旦成功,新的传入请求将被定向到它,然后IIS等待第一个AppDomain(正在关闭的那个)完成处理它的任何请求。
结果是存在两个AppDomain的重叠,两者都具有相同的
instance_name
值。然而,并非所有问题都得到解决。我在代码中纠正了这个问题,将进程ID作为示例名的一部分。但它似乎引入了另一个问题--我认为是进程范围的性能计数器似乎永远不会在不重新启动计算机的情况下消失。(这可能是我的一个bug,所以YMMV)。
这是我用来创建示例名的例程:
jhkqcmku3#
我不是自定义计数器的Maven,但根据您提供的信息,我认为这是值得一试的,考虑到一些代码在添加域即将被回收时尝试使用计数器的可能性。在任何与dispose或析构函数相关的东西中查找计数器的用法。
mepcadol4#
如果延迟创建性能计数器,则可能是线程问题。在进程回收之后,如果同时发生两个页面命中(这并不让我感到惊讶),那么您的性能创建调用可能会运行多次。一方面,您可以安全地忽略此错误。但是如果你想消除它,我建议你用一个lock语句来 Package 你的性能计数器代码生成,比如
vc9ivgsu5#
我遇到了类似的问题:多示例,进程生存期计数器不能在Visual Studio中创建一次以上,但这是因为我打开了PerfMon!
我花了一段时间才意识到。
qeeaahzv6#
IIS保证您的第一个AppDomain在启动第二个AppDomain之前不会关闭,特别是当您手动或自动回收它时,如果您将应用程序池回收“禁用重叠回收”属性设置为false(默认值)。
在共享主机的情况下,您可以在web.config文件中定义。