6

我们有一个 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>
    
4

3 回答 3

6

正如 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 本身的性能问题。

于 2012-11-19T14:29:24.090 回答
5

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

于 2012-12-09T09:10:41.847 回答
4

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

对于越来越多的内存,这听起来像是标准的内存泄漏或至少是 GC 问题。您是否使用实体框架,您是否使用 Red Gates Memory Profiler 之类的工具进行分析,而不是内置的 VS 分析器?

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

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

于 2012-11-19T10:04:22.043 回答