内存泄漏 - WCF异常

时间:2012-02-23 17:30:53

标签: wcf asp.net-mvc-3 memory-leaks ninject

我的ASP.NET MVC3应用程序使用Ninject通过包装器实例化服务实例。控制器的构造函数有一个IMyService参数,动作方法调用myService.SomeRoutine()。使用wsHttpBinding通过SSL访问服务(WCF)。

我有一个搜索例程,它可以返回如此多的结果,超过我在WCF中配置的最大值(在对象图中可以序列化或反序列化的最大项目数)。发生这种情况时,服务和客户端的应用程序池都会显着增长,并在请求结束后保持膨胀。

我知道我可以限制结果数量或使用DTO来减少传输的数据量。也就是说,我想解决看起来像是内存泄漏的问题。

使用CLR Profiler,我发现以下使用了大量的堆:

  • System.RunTime.IOThreadTimer.TimerManager
  • System.RunTime.IOThreadTimer.TimerGroup
  • System.RunTime.IOThreadTimer.TimerQueue
  • System.ServiceModel.Security.SecuritySessionServerSettings
  • System.ServiceModel.Channels.SecurityChannelListener
  • System.ServiceModel.Channels.HttpsChannelListener
  • System.ServiceModel.Channels.TextMessageEncoderFactory
  • System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder
  • System.Runtime.SynchronizedPool
  • System.Runtime.SynchronizedPool.Entry []
  • ... TextMessageEncoderFactory.TextMessageEncoder.TextBufferedMessageWriter
  • System.Runtime.SynchronizedPool.GlobalPool
  • System.ServiceModel.Channels.BufferManagerOutputStream
  • System.Byte [] []
  • System.Byte [](92%)

此外,如果我修改搜索例程以返回一个空列表(当NHibernate的东西仍在后台继续 - 通过日志验证),应用程序池大小保持不变。如果搜索例程在没有异常的情况下返回重要结果,则应用程序池大小保持不变。我相信当序列化对象列表并导致异常时会发生泄漏。

我升级到最新的Ninject,我使用log4net验证服务客户端是否已关闭或中止,具体取决于其状态(状态从未出现故障)。我发现唯一有趣的是服务包装器正在最终确定而没有明确处理。

我无法对此进行故障排除,以找出我的应用程序池在此方案中未释放内存的原因。我还应该注意什么?

更新:这是绑定...

<wsHttpBinding>
 <binding name="wsMyBinding" closeTimeout="00:01:00" openTimeout="00:01:00" 
  receiveTimeout="00:02:00" sendTimeout="00:02:00" bypassProxyOnLocal="false" 
  transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
  maxBufferPoolSize="999999" maxReceivedMessageSize="99999999" 
  messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false" 
  allowCookies="false">
  <readerQuotas maxDepth="90" maxStringContentLength="99999" 
  maxArrayLength="99999999" maxBytesPerRead="99999" 
  maxNameTableCharCount="16384" />
  <reliableSession enabled="false" />
  <security mode="TransportWithMessageCredential">
   <message clientCredentialType="UserName" />
  </security>
 </binding>
</wsHttpBinding>

UPDATE#2 :这是Ninject绑定,但更奇怪的是错误消息。我的包装器没有正确设置MaxItemsInObjectGraph所以它使用了默认值。一旦我设置了这个,泄漏就消失了。当服务将序列化数据发送到客户端并且客户端因为它超过MaxItemsInObjectGraph而拒绝它时,客户端和服务似乎将序列化/反序列化数据保留在内存中。

Ninject Binding:

Bind<IMyService>().ToMethod(x => 
    new ServiceWrapper<IMyService>("MyServiceEndpoint")
    .Channel).InRequestScope();

错误消息:

  

InnerException消息是'可以的最大项目数   对象图中的序列化或反序列化为“ 65536

这实际上并没有解决内存泄漏的问题,所以如果有人有任何想法,我仍然很好奇是什么导致了它。

1 个答案:

答案 0 :(得分:1)

您如何处理代理客户端的创建和处理?

我发现与WCF相关的内存泄漏的最常见原因是错误处理WCF代理客户端。

我建议至少为您的客户打包using块,如下所示:

using (var client = new WhateverProxyClient())
{
  // your code goes here
}

这可以确保正确关闭和处理客户端,释放内存。

这种方法虽然有点争议,但它应该消除了从客户端创建中泄漏内存的可能性。

有关此主题的更多信息,请查看here