返回相当大的数据集时,WCF服务的IIS响应非常延迟

时间:2011-08-10 18:10:09

标签: wcf iis-7

我有一个IIS 7托管的WCF服务,主要用于通过实体框架返回数据。其中一个操作契约/服务方法返回大约17000个非常简单且相当小的实体对象的列表。响应大小最终大约为6.5MB,所以它并不大。当我使用IIS Express在我的开发计算机上托管服务时,将进行服务调用并立即(10秒内)回发数据。当我将服务推送到我们的服务器时,响应平均需要1:46秒才能恢复。在Web服务器上进行一些跟踪后,我发现获取数据的方法只需要6秒钟即可返回。在这种情况下,服务器大约需要1:40秒来准备然后发送响应(我已在网络日志中确认,因此这不是网络延迟问题。)

这些是我在服务定义中唯一的配置:

  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

这就是我的web.config的样子:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <httpRuntime executionTimeout="600" />
  </system.web>
  <system.serviceModel>

    <services>
      <service behaviorConfiguration="RGDataBehavior" name="WCFData.Web.Services.DataAccess">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="LargeBuffer" name="RGData_http" contract="WCFData.Web.Services.IDataAccess" listenUriMode="Explicit"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://myurl.com/Services/Data.svc"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <bindings>
      <basicHttpBinding>
        <binding name="LargeBuffer"
                 closeTimeout="00:10:00"
                 openTimeout="00:10:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 transferMode="StreamedResponse"
                 maxBufferPoolSize="2147483647"
                 maxBufferSize="2147483647"                 
                 maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxStringContentLength="2147483647"
                        maxNameTableCharCount="2147483647"/>
        </binding>
      </basicHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="RGDataBehavior">
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          <serviceMetadata httpGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceAuthorization
            serviceAuthorizationManagerType="WCFData.Web.Authentication.WCFAuthenticator,
                                             Data.Web.Authentication"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

我一直在讨论这个问题,而且我发现的大部分内容似乎都不符合要求,所以如果有人有建议,我会很乐意帮忙。提前谢谢。

2 个答案:

答案 0 :(得分:0)

我建议启用WCF trace logging,这可能有助于从WCF内部获取更多的时间数。

你也可以通过一个分析工具运行服务器,并试着缩短确切的方法,但是我不确定是否有一种通过IIS做到这一点的好方法。

如果所有其他方法都失败了,您可以在服务器处理时(在此1m40s处理时间内)始终进行一些线程转储,并查看每个线程的堆栈跟踪以查看可能卡住的内容。我通常使用安装了Debugging Tools for Windows包的ntsd.exe命令行调试器来执行此操作。


编辑:

这是另一个想法。由于您认为它与序列化直接相关,因此您可以隔离DataContractSerializer和时间序列化数据所需的时间。代码看起来像:

[OperationContract]
public YourData[] YourServiceMethod()
{
    YourData[] data = ... // get all your data here as usual.

    // lets serialize it and time how long it takes
    var timer = new System.Diagnostics.Stopwatch();
    timer.Start();
    var dataContractSerializer = new System.Runtime.Serialization.DataContractSerializer(data.GetType());
    using (var memoryStream = new System.IO.MemoryStream())
    {
        dataContractSerializer.WriteObject(memoryStream, data);
    }
    timer.Stop();

    System.Console.WriteLine(timer.ElapsedMilliseconds); // Log this, or whatever...

    // return now as normal (WCF will re-serialize, talking even longer, but this is just a test anyway)
    return data;
}

答案 1 :(得分:0)

我的问题的答案更多的是解决问题的真正解决方案。更改服务方法以返回字节数组而不是集合,以便IIS不必将XML序列化集合写入响应中来解决问题,但它仍然无法解释为什么延迟发生在第一位。我使用protobuf-net library将我的返回集合序列化为字节数组,然后再次在客户端反序列化数组。