记忆与处理 ServiceHost 中的泄漏

发布于 2024-12-07 14:08:51 字数 2294 浏览 0 评论 0原文

我的服务应用程序中有一个 ServiceHost,每 60 秒与 1700 个客户端进行通信。当我启动服务时,它几乎立即攀升到大约 1500 个打开的句柄,然后在大约 5 分钟后继续添加另外 300 个(并在此之后继续继续前进。)

我查看了 ProcessExplorer,在拆分视图中,它显示了数百个名为“Device\Afd”的文件类型句柄 - 它代表用于通信的 TCP 套接字(我相信)。

我只是假设我的句柄泄漏与 ServiceHost 有关,因为它代表从 Process Explorer 观察到的最高句柄数。我想知道为什么该服务不关闭这些?我是否需要设置某种超时,或者我是否需要在某个地方主动关闭它们?

以下是我的 ServiceHost 的创建方式:

wcfObject = new WcfObject();
host = new ServiceHost(wcfObject, baseWcfAddress);

ServiceBehaviorAttribute attribute = (ServiceBehaviorAttribute)host.Description.Behaviors[typeof(ServiceBehaviorAttribute)];
attribute.ConcurrencyMode = ConcurrencyMode.Multiple;
attribute.InstanceContextMode = InstanceContextMode.Single;

在我的 app.config 中:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="WcfObject" behaviorConfiguration="DefaultBehavior">
        <host>
          <baseAddresses >
            <!-- Defined in code -->
          </baseAddresses>
        </host>
        <endpoint name="NetTcpEndPoint" address="" binding="netTcpBinding" bindingConfiguration="netTcpBinding" contract="IWcfObject"/>
        <endpoint name="NetTcpMetadataPoint" address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBinding" maxReceivedMessageSize="9655360" maxBufferSize="9655360" maxBufferPoolSize="524288">
          <readerQuotas maxArrayLength = "932000" maxStringContentLength="900000" maxDepth="32"/>
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior" >
          <serviceMetadata httpGetEnabled="False" httpGetUrl="" />
          <serviceDebug includeExceptionDetailInFaults="True"/>
          <serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="100" />          
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

I've got a ServiceHost in a service app that communicates with 1700 clients every 60 second. When I start the service, it climbs to about 1500 open handles almost immediately, then continues to add another 300 after about 5 minutes (and continues onward continuously after that.)

I've looked at ProcessExplorer and in Split view, it shows hundreds of handles of type File named "Device\Afd" - which is a representative of the TCP socket being used to communicate (I believe).

I'm only assuming that my handle leak is related to the ServiceHost because it represents the highest number of handles observed from Process Explorer. What I'm wondering is why doesn't the service close these? Do I need to set a timeout of some sort or do I need to actively close them myself somewhere?

Here's how my ServiceHost is created:

wcfObject = new WcfObject();
host = new ServiceHost(wcfObject, baseWcfAddress);

ServiceBehaviorAttribute attribute = (ServiceBehaviorAttribute)host.Description.Behaviors[typeof(ServiceBehaviorAttribute)];
attribute.ConcurrencyMode = ConcurrencyMode.Multiple;
attribute.InstanceContextMode = InstanceContextMode.Single;

And in my app.config:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="WcfObject" behaviorConfiguration="DefaultBehavior">
        <host>
          <baseAddresses >
            <!-- Defined in code -->
          </baseAddresses>
        </host>
        <endpoint name="NetTcpEndPoint" address="" binding="netTcpBinding" bindingConfiguration="netTcpBinding" contract="IWcfObject"/>
        <endpoint name="NetTcpMetadataPoint" address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBinding" maxReceivedMessageSize="9655360" maxBufferSize="9655360" maxBufferPoolSize="524288">
          <readerQuotas maxArrayLength = "932000" maxStringContentLength="900000" maxDepth="32"/>
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior" >
          <serviceMetadata httpGetEnabled="False" httpGetUrl="" />
          <serviceDebug includeExceptionDetailInFaults="True"/>
          <serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="100" />          
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感情洁癖 2024-12-14 14:08:51

我认为您的具体问题已描述 此处

当通道创建并且操作上下文存在时,则
每个新通道实例都附加在 WmiChannel 列表中(请参阅
下面代码中的属性 InstanceContext.WmiChannels)。这份清单导致
泄漏。但是,如果在每次调用时重新创建 InstanceContext
操作(即在 PerCall 上设置 InstanceContextMode 时),
列表将被重新创建,并且不会导致泄漏。

有关解决方法,请参阅同一篇文章。请随时告知我们您的发现。

I think your specific problem is described here.

When the channel is created and the operation context exists, then
each new channel instance is appended in the list of WmiChannels (see
property InstanceContext.WmiChannels in code below). This list causes
the leak. However if the InstanceContext is recreated on each invoke
of operation (that is when InstanceContextMode is set on PerCall), the
list will be recreated and no leak will be caused.

For a workaround, see the same post. Please keep us informed of your findings.

世俗缘 2024-12-14 14:08:51

事实证明,我是从 [STAThread] 运行我的服务 - 每当应用程序使用 COM 调用时,除非您运行 [MTAThread] 模式,否则您可能会泄漏内存。

As it turns out, I was running my service from a [STAThread] - anytime an app uses COM calls, you'll potentially leak memory unless you are running [MTAThread] mode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文