Производительность WCF, передающая список объектов с использованием wsHttpBinding

#c# #wcf

#c# #wcf

Вопрос:

Я пытаюсь сократить время, затрачиваемое на отправку списка объектов DTO через Интернет с использованием wsHttpBinding. Безопасность — это TransportWithMessageCredential с сертификатом X509. Время составляет около 2,5 с для 500 объектов в списке, использование базового HttpBinding без защиты экономит всего несколько миллисекунд.

Изменение messageEncoding на Mtom, казалось, еще больше замедлило его. Я добавил трассировку и просмотрел файлы с помощью SvcTraceViewer, и самое долгое показанное время было после отправки сообщения, когда была граница активности, затем «Сеанс безопасности сервера получил сообщение о закрытии от клиента», которое составляло 1,5 секунды, передача, казалось, заняла всего 400 мс.

Я добавил следующие атрибуты контекста и параллелизма к классу service

  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,ConcurrencyMode=ConcurrencyMode.Multiple)]
  

В классах DTO я добавил имя к элементу данных, чтобы сократить время десериализации

   [Serializable]
[DataContract(Name="Sample")]
public class Sample
{
    [DataMember(Name="Id")]
    public int Id { get; set; }
  

В файле service Web.Config поведение

   <behaviors>
  <serviceBehaviors>
    <behavior name="MyBehavior">
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
      <serviceMetadata httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
      <serviceThrottling maxConcurrentCalls="300" maxConcurrentSessions="5000"  maxConcurrentInstances="300" />
    </behavior>
    <behavior>
      <serviceMetadata httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>
  

Клиентский Web.Config имеет привязку

    <wsHttpBinding>
    <binding name="MyEndpoint" 
             closeTimeout="00:01:00" 
             openTimeout="00:01:00"
             receiveTimeout="00:10:00" 
             sendTimeout="00:01:00" 
             bypassProxyOnLocal="false"
             transactionFlow="false" 
             hostNameComparisonMode="StrongWildcard"
             maxBufferPoolSize="524288" 
             maxReceivedMessageSize="2147483647"
             messageEncoding="Mtom" 
             textEncoding="utf-8"
             useDefaultWebProxy="false"
             allowCookies="false"  >
      <readerQuotas 
            maxDepth="2147483647" 
            maxStringContentLength="2147483647" 
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647" 
            maxNameTableCharCount="2147483647" />
      <reliableSession 
            ordered="true" 
            inactivityTimeout="00:10:00"
            enabled="false" />
      <security mode="TransportWithMessageCredential">
        <transport 
            clientCredentialType="None"  />
        <message 
            clientCredentialType="Certificate"  />
      </security>
    </binding>
  </wsHttpBinding>
  

и настройка поведения

  <behavior name="MyBehavior">
              <dataContractSerializer maxItemsInObjectGraph="2147483647" />
              <clientCredentials>
                  <clientCertificate findValue="xxxxxxx" storeLocation="LocalMachine" x509FindType="FindByThumbprint" />
              </clientCredentials>
          </behavior>
  

Есть ли какие-либо предложения, как сделать это быстрым и масштабируемым?

РЕШЕНИЕ Оказывается, что gzip на самом деле не был установлен в IIS, как мы предполагали. Я обязательно буду тестировать protobuf-net Марка Гравелла для производства, однако gzip решил насущную проблему.

Комментарии:

1. Насколько велики объекты — сколько данных поступает по проводам — и являются ли они локальными или удаленными? Насколько удалены пользователи?

2. Это выполняется через Интернет Windows 2008 r2 server iis 7, как клиент, так и сервер. Я не измерял размер данных, подойдет ли для этого fiddler? Объект представляет собой 18 полей string и int, каждый объект имеет размер около 900 символов в XML-сообщении.

Ответ №1:

Вы могли бы значительно выиграть от использования сжатия GZip.

Ответ №2:

Посмотрите на PROTOBUF: Проверка буферов протоколов

У вас также есть .net-версия: protobuf-net

Ответ №3:

Здесь фактором может быть время пропускной способности и время сериализации / десериализации. Кроме того, время защиты при транспортировке будет примерно зависеть от размера полосы пропускания. Я предлагаю, чтобы одна вещь, на которую вы могли бы обратить внимание здесь, заключалась бы в сокращении времени пропускной способности. Отказ от ответственности: Я автор (но я ничего не продаю; все это бесплатно / OSS) — но: protobuf-net использует гораздо более плотный формат данных, чем DataContractSerializer , и имеет перехваты для подключения к WCF для замены сериализатора. При использовании этого вы бы в идеале хотели, чтобы MTOM был включен, поскольку он двоичный. Это может быть сделано либо явно, либо через конфигурацию. Обратите внимание, что это работает проще всего, если оба конца используют совместное использование сборки; если вы используете «mex» для создания клиентской половины, могут потребоваться некоторые дополнительные шаги.

Комментарии:

1. Спасибо, Марк, я попробую protobuf-net. Вероятно, я использую mex, но я контролирую оба конца, поэтому рассмотрю общий доступ к сборке.

2. @Paul Я не могу гарантировать, что это поможет в каждом отдельном сценарии, но обычно это хорошо работает