Каков будет максимальный размер буфера в привязках WCF? - PullRequest
0 голосов
/ 04 октября 2011

У меня есть senario, где я должен загрузить некоторые данные, используя службу WCF, что я смог успешно выполнить, если размер загружаемого контента меньше 1 МБ, но если размер загружаемого контента больше 1 МБ, я получаю сообщение об ошибке типаthis

Сообщение об ошибке: -

Произошла ошибка при получении ответа 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>

Может кто-нибудь знает обходной путь для этого, пожалуйста?может быть размером до 2 ГБ. Так что же может быть точный размер буфера или maxReceivedMessageSize или maxStringContentLength, который я должен дать?

1 Ответ

2 голосов
/ 04 октября 2011

OMG. Когда MS представила WCF, они действительно должны упомянуть, что это не технология загрузки / выгрузки данных или, по крайней мере, не напрямую без дополнительного кодирования.

Ваш сервис ужасен, и для 2 ГБ он, скорее всего, все равно не будет работать, поскольку использует буферизованную передачу и обычное кодирование текста. Это означает, что каждые 2 ГБ будут сначала загружены с диска в память клиентского компьютера с кодировкой Base64 (размер + 33%). Хранится в одном сообщении SOAP и передается на сервер, где все сообщение должно быть загружено в память, декодировано и обработано. Любая проблема в сети, и все сообщение исчезло. Любой тайм-аут и все сообщение исчезло. Btw. ваш MaxReceivedMessageSize настроен на 260 МБ = после считывания 260 МБ служба выдаст неверный запрос.

Одновременно выполняется несколько таких загрузок, и ваш сервер не работает. Сервер будет открыт для присоединения к отказу в обслуживании настолько, насколько это возможно.

Для диагностики вашей ошибки используйте трассировка WCF на стороне сервера. Чтобы узнать о передаче больших сообщений, прочитайте эту статью . Это поможет вам определить сервис, который работает лучше, но все равно будет довольно ненадежным. Лучший способ - это использовать некоторые фрагменты и передавать большие наборы данных в нескольких вызовах, разложив их на клиенте и перекомпоновав на сервере. Для повышения надежности и восстановления после сбоя клиент должен иметь возможность продолжить работу после сбойного чанка, а не передавать весь набор данных снова.

Существуют и другие функции, такие как сжатие для уменьшения размера передаваемых данных и CRC для проверки того, что передаваемые данные не были искажены при передаче.

ИМХО, это может быть намного лучше и проще реализовано без WCF с прямым использованием HttpListener или универсального обработчика ASP.NET и фрагментированного HTTP-заголовка транспорта и заголовка диапазона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...