Подтвердить что ты не робот

WCF Параллельные запросы нагромождения на сервере при использовании WSHttpBinding

У меня есть клиентское/серверное приложение WCF, которое обменивается HTTP через WSHttpBinding.

Настройка сервера: самостоятельный хостинг, используя стандартный WCF ServiceHost. Мой фактический класс обслуживания присваивается как:

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

Настройка клиента: используя созданный визуально-студийный клиентский прокси-сервер с использованием синхронных вызовов службы (proxy.call_server_method блокирует до тех пор, пока сервер не ответит полностью.)

Сценарий: У меня есть один конкретный вызов метода, который занимает 20 секунд для выполнения на сервере. Клиент вызывает этот метод в отдельном потоке, поэтому он не удерживается, а ConcurrencyMode.Multiple означает, что WCF должен выполнять его в отдельном потоке на сервере.

Эта теория подтверждается тем фактом, что при настройке моего приложения на использование NetTcpBinding все работает нормально.

Проблема:
Если я настрою приложение на использование WSHttpBinding, то этот длинный вызов метода заставит HTTP-запросы "резервную копию". Я проверил это поведение как от проверки моих журналов, так и от отладки HTTP-запросов с помощью скрипача.

Пример:

  • Клиент инициирует 20-секундный длинный запрос в фоновом потоке
  • Клиент инициирует запрос B и C на переднем плане
  • Запросы B и C отправляются на сервер, который не обрабатывает их до тех пор, пока он не будет выполнен с 20-секундным длинным запросом

Но иногда:

  • Запросы B и C не отправляются (они даже не появляются в скрипачках), пока не возвращается 20-секундный запрос (это редко).
    • Примечание: установка <add address="*" maxconnection="100"/> в клиенте app.config сделала это (кажется) прекратить.
  • Запрос B отправляется и сразу получает ответ, в то время как запрос C удерживается до завершения 20-секундного завершения (это редко)

Здесь показана временная шкала от скрипача, демонстрирующая проблему: (нажмите для увеличения)

3510636841_18f9b2b0a1.jpg

Как вы можете видеть, все запросы выполняются на сервере. Как только 20-секундный запрос завершается, все ответы наступают, но обратите внимание, что есть некоторые запросы, которые не получают поддержки...

Итак, Вопросы:

  • Что, черт возьми, происходит здесь? Почему он работает нормально, используя NetTcpBinding и не работает с помощью WSHttpBinding?
  • Почему несовместимое поведение?
  • Что я могу сделать, чтобы исправить это?

Примечания:

  • Он не блокируется на сервере. Я установил точки останова и использовал !syncblk, и он постоянно сообщает, что блокировки не хранятся.
  • Это не моя нить (NetTcpBinding не должно работать иначе)
  • У меня <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" /> установлен на сервере app.config
  • 20-секундный вызов просто ждет таймера, он не разбивает процессор, диск или сеть.
  • Я бы предпочел решение, которое не включало бы повторное архивирование приложения для использования асинхронных вызовов... это большая группа устаревшего кода, и я действительно не хочу возиться с вещами, которые я не понимаю.
4b9b3361

Ответ 1

[Self-answer, чтобы показать другим пользователям, какое было наше возможное решение]

В конце концов, мне так и не удалось это решить.
Наше окончательное решение заключалось в том, чтобы отключить наше приложение от WSHttpBinding и на NetTcpBinding в производстве - мы планировали сделать это в конечном итоге в любом случае по соображениям производительности.

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

Ответ 2

Существует некоторая дроссельная заслонка вне WCF (объект .Net или Windows), которая по умолчанию позволяет не более двух одновременных исходящих HTTP-соединений. К сожалению, я не могу вспомнить, что жизнь меня - это имя вещи (и то, что вы добавили бы в app.config или ваше приложение, чтобы переопределить его). Учитывая, что вы не видите, что запросы покидают клиент, и что это только HTTP, я думаю, что вы нажимаете "это". Я буду продолжать искать его имя.

Обновление: Найденное - попробуйте это на клиенте (но измените "2" на большее число):

<configuration>
  <system.net>
    <connectionManagement>
      <add address = "*" maxconnection = "2" />
    </connectionManagement>
  </system.net>
</configuration>

Ответ 3

Мы видели точно такие же симптомы с сервисом JSON, размещенным в IIS/ASP.NET.

Основная причина в том, что ASP.NET синхронизирует запросы, а не WCF. Нам пришлось отключить состояние сеанса (на уровне приложения), чтобы получить совпадающие методы WCF.

Web.config: <system.web> <sessionState mode="Off" /> </system.web>

Обратите внимание, что наша служба использует webHttpBinding, а не wsHttpBinding. Итак, я не уверен, что это также решает проблему Ориона.

Ответ 4

Я думаю, что вы попали в предел протокола и для его работы вам нужно изменить стандартные настройки на клиентской машине:

http://support.microsoft.com/kb/183110

http://support.microsoft.com/kb/282402

Я предполагаю, что WSHttpBinding использует настройки WinINET при выдаче запросов.

Ответ 5

Если вы переходите на BasicHttpBinding, это работает?

Это так, это звучит как это твоя проблема, дросселирование сеанса, что-то, что укусило меня в заднице.

Ответ 6

Рассмотрим использование ConcurrencyMode.Multiple для сервисов для каждого вызова, чтобы разрешить одновременную вызовы.

Ответ 7

Я забыл - может ли это быть заказ? Я думаю, возможно, RM поверх http сохраняет заказ, но, возможно, сеансы Tcp не (если вы явно не запросите его)? Есть ли атрибут в контракте на обслуживание, описывающий упорядоченные/неупорядоченные сеансы (я забыл).

Ответ 8

Не уверен, но иногда проблема с одновременными вызовами приложения silverlight связана с управлением соединениями с браузером. Для меня решение заключалось в том, чтобы поместить это в наш метод App.xaml.cs, Application_Startup как описано здесь: http://weblogs.asp.net/olakarlsson/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);