内存泄漏 - WCF异常

内存泄漏 - WCF异常

问题描述:

我的ASP.NET MVC3应用程序使用Ninject通过包装实例化服务实例。控制器的构造函数具有IMyService参数,操作方法调用myService.SomeRoutine()。服务(WCF)通过SSL通过wsHttpBinding进行访问。内存泄漏 - 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> 

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

Ninject绑定:

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

错误消息:

设置InnerException消息是 '项目的最大数目,可以是 串行化或在对象图反序列化是' '

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

+0

你用什么捆绑包装? – 2012-02-23 23:21:07

+0

@Remo:我添加了上面的绑定 - 谢谢! – Mayo 2012-02-24 14:00:09

+0

对不起,我不够清楚。我的意思是用于创建包装的Ninject绑定。特别是范围是有趣的。 – 2012-02-24 15:01:10

你是如何处理你的代理客户端创建和处置的?

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

我建议至少是有using块包裹你的客户还挺像这样:

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

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

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

查看here了解更多关于此主题的信息。

+0

感谢您的反馈,使用此绑定时,应将包装器置于MVC请求的末尾。服务包装器有一个dispose和finalize,它们确保客户端在被设置为null之前关闭/中止(使用类似于该文章的代码)。我想我会创建一个测试工具来试验这个场景的变体来尝试隔离泄漏。太多的变数现在。 – Mayo 2012-02-23 20:57:15

+5

-1:既然你知道那篇文章,为什么你会建议任何人使用'using'块? – 2012-02-24 00:30:07