WCF服务在第一次调用时达到高内存使用率

时间:2012-11-19 09:47:24

标签: c# .net wcf web-services iis

我们将WCF服务作为BL服务。 该服务处于混合传输模式,具有超过10个不同的端点,由BasicHttpBinding绑定,具有不同的合同和所有这些的相同地址。 该服务在IIS-7上的应用程序池上运行。

问题是,服务工作正常,但是在第一次调用之后,即使获得WSDL,w3wp.exe的内存使用量也直接达到300兆,服务内存使用率不断增加,接管所有服务器的物理内存(98 - 100%)。我们没有内存异常,但是这种情况会降低其他应用程序和服务的速度,因此我们需要每隔几天手动刷新一次应用程序池。 我已经尝试使用内存分析工具,但没有发现导致问题的原因。

有没有人遇到过这个问题?如果是的话,你做了什么?

其他信息:

  • BL服务位于基于NHibernate的DAL框架之上, 我们已经排除了内存泄漏源于那里。
  • 配置文件

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <appSettings>
        </appSettings>   
        <system.web>
            <compilation debug="true" targetFramework="4.0" />
            <httpRuntime maxRequestLength="20000" requestLengthDiskThreshold="20000" />
        </system.web>     
        <system.serviceModel>     
            <behaviors>
                <serviceBehaviors>
                    <behavior name="DefaultServiceBehavior">
                        <serviceMetadata httpGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="true" />
                    </behavior>
                </serviceBehaviors> 
    
                <endpointBehaviors>
                    <behavior name="AnonymousBehavior">
                    </behavior>
                </endpointBehaviors>
          </behaviors>
    
          <bindings>
              <basicHttpBinding>
                  <binding name="SecureBinding" 
                   closeTimeout="00:10:00" 
                   openTimeout="00:10:00" receiveTimeout="00:10:00" 
                   sendTimeout="00:10:00" allowCookies="true" 
                   hostNameComparisonMode="StrongWildcard" maxBufferSize="65536000" 
                   maxBufferPoolSize="524288000" maxReceivedMessageSize="65536000" 
                   transferMode="Buffered">
                      <readerQuotas maxDepth="20000000"
                       maxStringContentLength="8192000"
                       maxArrayLength="16384000"
                       maxBytesPerRead="4096000"
                       maxNameTableCharCount="16384000" />
                          <security mode="None">
                              <transport clientCredentialType="None"/>
                          </security>
                  </binding>
             </basicHttpBinding>         
        </bindings>
    
    <services>
    <service name="BL.Services.MyService"
    behaviorConfiguration="DefaultServiceBehavior">
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Security/Anonymous"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.IAnonymousClaimsService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/App"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.IAppService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/App"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.IAttachmentService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/Site"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.ISecurityService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/Transaction"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.ITransactionService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/ActiveDirectory"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.IActiveDirectoryService" />
    
    <endpoint address=""
    binding="basicHttpBinding"
    bindingConfiguration="SecureBinding"
    bindingNamespace="Domain/Report"
    behaviorConfiguration="WithSecurityContextInspector"
    contract="BL.Services.Contracts.IReportService" />
    
    <host>
    <baseAddresses>
    <add baseAddress="//MyService.svc" />
    </baseAddresses>
    </host>
    </service>
    </services>
    
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <defaultDocument>
    <files>
        <add value="MyService.svc" />
    </files>
    </defaultDocument>
    </system.webServer>
    </configuration>
    

3 个答案:

答案 0 :(得分:5)

AnkMannen指出,300MB并不罕见。大量使用的服务可以轻松达到约700MB或更高的平台。您对耗尽大多数可用服务器内存但未触发内存不足异常的服务的第二次观察可能是由于非默认配置值:

binding:
maxBufferSize="65536000"
maxBufferPoolSize="524288000"
maxReceivedMessageSize="65536000"
transferMode="Buffered"

readerQuotas:
maxDepth="20000000"
maxStringContentLength="8192000"
maxArrayLength="16384000"
maxBytesPerRead="4096000"
maxNameTableCharCount="16384000"

您实际上正在配置WCF以使用您选择的值消耗过多的内存。除非您遇到需要更改任何属性的默认值的特定条件,否则请勿更改它们。我常规更改的唯一值是maxReceivedMessageSize,默认值为64K,大约为1到2 MB,如果不可避免的话。如果您经常使用大于3 MB的邮件,则应重新考虑数据协定设计。 WCF被指责的许多性能问题实际上是错误配置,而不是WCF本身的性能问题。

答案 1 :(得分:4)

经过长时间的搜索,我们发现了问题。 我们的服务在一个工作单元中使用了很多逻辑单元。 每个逻辑单元都继承自BaseLogic类。在BaseLogic单元中有一个Enterprise Library UnityContainer属性,它创建了一个工厂。每次调用都会创建此工厂的许多实例,将此属性更改为静态属性可以解决问题。

答案 2 :(得分:3)

首次跳转到300MB与我在应用程序中看到的一致。还没有真正找到减少这个数字的方法,但随着时间的推移它会保持这个数字。

对于增加的内存部分,它听起来像标准内存泄漏或至少是GC问题。您使用的是实体框架吗?您是否使用Red Gates Memory Profiler等工具进行了配置文件,而不是内置的VS Profiler?

根据问题中的信息,很难给出更具体的答案。

同时,尝试使用应用程序池的IIS自动刷新。将其设置为您选择的阈值,并让它自动处理刷新。