【问题标题】:WCF Service Memory LeaksWCF 服务内存泄漏
【发布时间】:2011-02-18 14:10:27
【问题描述】:

我在控制台应用程序中托管了一个非常小的 wcf 服务。

[ServiceContract]
public interface IService1
{
    [OperationContract]
    void DoService();
}

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class Service1 : IService1
{
    public void DoService()
    {

    }
}

它被称为

using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
{
    client.DoService(new DoServiceRequest());
    client.Close();
} 

请记住,服务是在 basicHttpBindings 上发布的。

问题

现在,当我在 1000 次循环中执行上述客户端代码时,我发现“所有堆字节”和“私有字节”性能计数器之间存在很大差异(我使用了 .net 内存分析器)。经过调查,我发现有些物品没有妥善处理 以下是这些对象的列表(找到了 1000 个未处理的实例 --> 等于客户端调用)

(它们的命名空间都是 System.ServiceModel.Channels)

HttpOutput.ListenerResponseHttpOutput.ListenerResponseOutputStream
BodyWriterMessage
BufferedMessage
HttpRequestContext.ListenerHttpContext.ListenerContextHttpInput.ListenerContextInputStream
HttpRequestContext.ListenerHttpContext 

问题 为什么我们有很多未处理的对象以及如何控制它们。

请帮忙

【问题讨论】:

  • 对我来说似乎是系统库泄漏。客户端(如在用户编写的服务中)代码不会触及这些缓冲区和流,并且看起来 WCF 没有处理它们。
  • Mabushar:你有运气吗?我似乎遇到了类似的问题。
  • @bugfixr 对不起兄弟我今天注意到你的消息,我不记得我是否能够摆脱那些但我记得的一件事是我从框架 3.5 转移到框架 4.0,它帮助部分或全部我不记得了,但它以某种方式帮助了我。抱歉回复晚了。

标签: wcf .net-3.5 memory-leaks


【解决方案1】:

您正在为每次调用请求一个新实例 (InstanceContextMode=InstanceContextMode.PerCall)。如果 1000 次调用中没有发生 GC,则服务实例将未被收集。 WCF 要求您实现 IDisposable

来自MSDN : Discover Mighty Instance Management Techniques For Developing WCF Apps

每次通话服务 每次调用服务是 Windows Communication Foundation 默认的实例化模式。当服务类型配置为每次调用激活时,服务实例即公共语言运行时 (CLR) 对象仅在客户端调用正在进行时存在。每个客户端请求都会获得一个新的专用服务实例。图 2 说明了这种单调用激活的工作原理。


(来源:microsoft.com

  1. 客户端调用代理和 代理将呼叫转发到 服务。
  2. Windows Communication Foundation 创建服务 实例并调用其上的方法。
  3. 方法调用返回后,如果对象实现 IDisposable,然后是 Windows 通信基金会电话 IDisposable.Dispose 就可以了。

【讨论】:

  • 我以前看过这篇文章,确实有它会自动调用 Dispose 方法,如果有的话,这只有你自己打开了一些资源并且需要清理,在这种情况下你需要自己清理它们。但就我而言,我没有资源可以清理。但是我已经尝试过这个但结果相同。此外,我想告诉您,GC 已经清理了堆,但由于这些对象被收集到 UNDisposed,因此未清理本机内存。
【解决方案2】:

我在 2010 年找到了解决方案,但我忘记发布了。我实际上失去了确切的轨迹,但我记得这是 .Net 库错误,它被报告给了微软并得到了他们的承认。我没有它的链接,但我会尽快找到它。无论如何,微软已经在 .net 4.0 中解决了这个问题,这就是我所遵循的确切解决方案,我知道对你们中的一些人来说,这可能是不可能的,因为有时你无法更改服务器环境。

【讨论】:

    【解决方案3】:

    您是否启用了性能计数器?像下面这样?

    <system.serviceModel>
      <diagnostics performanceCounters="All" />
      ..
    </system.serviceModel>
    

    在“增加性能计数器的内存大小”段落中,来自此链接: http://msdn.microsoft.com/en-us/library/ms735098.aspx

    当启用 WCF 性能计数器时,提到了“流氓”专用字节计数。将其更改为 ServiceOnly 或完全禁用它(关闭)可能会成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      相关资源
      最近更新 更多