Параллельные запросы WCF накапливаются на сервере при использовании WSHttpBinding - PullRequest
26 голосов
/ 07 мая 2009

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

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

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

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

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

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

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

Пример:

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

Но иногда:

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

Вот график от Fiddler, демонстрирующий проблему: (нажмите для увеличения)

image

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

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

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

Примечания:

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

Ответы [ 8 ]

11 голосов
/ 07 мая 2009

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

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

<configuration>
  <system.net>
    <connectionManagement>
      <add address = "*" maxconnection = "2" />
    </connectionManagement>
  </system.net>
</configuration>
4 голосов
/ 30 июня 2011

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

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

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

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

2 голосов
/ 30 июня 2011

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

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

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

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

2 голосов
/ 22 сентября 2009

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

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

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

1 голос
/ 09 января 2011

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

1 голос
/ 08 мая 2009

Если вы переключитесь на BasicHttpBinding, он будет работать?

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

0 голосов
/ 02 января 2015

Не уверен, но иногда проблема с одновременными вызовами из приложения 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);
0 голосов
/ 08 мая 2009

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

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