【问题标题】:What would be the maximum buffer size in WCF bindings?WCF 绑定中的最大缓冲区大小是多少?
【发布时间】:2011-10-04 08:27:11
【问题描述】:

我有一个场景,我必须使用 WCF 服务上传一些数据,如果上传的内容大小小于 1MB,我能够成功完成,但如果上传的内容大小大于 1MB,我会收到类似的错误这个

错误信息:-

接收到的 HTTP 响应时出错 “http://localhost/abc/Admin/Services/Package”。这可能是 由于服务端点绑定不使用 HTTP 协议。这 也可能是由于 HTTP 请求上下文被 服务器(可能是由于服务关闭)。查看服务器日志 了解更多详情。

我认为这是关于我在 app.config 中的绑定中的缓冲区大小设置的错误。

我的 app.config 文件客户端设置如下所示。

<system.serviceModel>
    <client>
      <endpoint address="http://localhost/abc/Services/Package"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_PackageService"
        contract="PackageService.PackageService" name="BasicHttpBinding_PackageService" />
    </client>
    <services>
      <!-- This section is optional with the new configuration model
           introduced in .NET Framework 4. -->
      <service name="ServiceContracts.SearchServiceContract"
               behaviorConfiguration="SearchServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/xyz/SearchService"/>
          </baseAddresses>
        </host>
        <!-- this endpoint is exposed at the base address provided by host: http://localhost:8080/xyz/SearchService  -->
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="NoSecurityBinding"
                  contract="ServiceContracts.ISearchServiceContract" />
        <!-- the mex endpoint is exposed at http://localhost:8080/xyz/SearchService/mex -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
      <service name="ServiceContracts.PackageServiceContract"
               behaviorConfiguration="PackageServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/xyz/PackageService"/>
          </baseAddresses>
        </host>
        <!-- this endpoint is exposed at the base address provided by host: http://localhost:8080/xyz/PackageService  -->
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="NoSecurityBinding"
                  contract="ServiceContracts.IPackageServiceContract" />
        <!-- the mex endpoint is exposed at http://localhost:8080/xyz/PackageService/mex -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SearchServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
        </behavior>
        <behavior name="PackageServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_PackageService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="268435456" maxBufferPoolSize="268435456" maxReceivedMessageSize="268435456"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
            maxBytesPerRead="268435456" maxNameTableCharCount="268435456" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="NoSecurityBinding">
          <security mode="None">
            <transport clientCredentialType="None" />
            <message establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>   
  </system.serviceModel>

请问有人知道解决方法吗?我的上传大小可以达到 2GB。那么我必须给出的确切缓冲区大小或 maxReceivedMessageSize 或 maxStringContentLength 是多少?

【问题讨论】:

    标签: wcf wcf-binding wcf-security wcf-data-services wcf-client


    【解决方案1】:

    天哪。当 MS 引入 WCF 时,他们真的应该提到它不是用于数据上传/下载的技术,或者至少不是直接没有额外编码的技术。

    您的服务很糟糕,对于 2GB,它很可能无论如何都无法工作,因为它使用缓冲传输和通用文本编码。这意味着每 2GB 将首先从磁盘加载到编码为 Base64 的客户端计算机的内存(+33% 大小)。存储到单个 SOAP 消息并传递到服务器,整个消息必须加载到内存中进行解码和处理。任何网络问题,整个消息都消失了。任何超时,整个消息都消失了。顺便提一句。您的 MaxReceivedMessageSize 配置为 260MB = 读取 260MB 后,服务将抛出错误请求。

    同时运行少量此类上传,您的服务器已死机。服务器将尽可能多地打开拒绝服务附加。

    要诊断您的错误,请在服务器端使用 WCF tracing。要了解如何传输大消息,请阅读this article。它将帮助您定义性能更好但仍然非常不可靠的服务。最好的方法是使用一些分块并在多个调用中传输大数据集,方法是在客户端分解它们并在服务器上重新组合它们。为了提高可靠性和故障恢复,客户端应该能够从故障块继续,而不是再次传输整个数据集。

    还有其他功能需要考虑,例如压缩以减小传输数据的大小,以及 CRC 以验证传输的数据没有因传输而出现格式错误。

    恕我直言,如果没有 WCF,直接使用 HttpListener 或通用 ASP.NET 处理程序和 HTTP 分块传输和范围标头,这可以更好、更容易地实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 2015-06-07
      • 1970-01-01
      • 1970-01-01
      • 2018-12-12
      • 1970-01-01
      相关资源
      最近更新 更多