2009-05-07 2 views
26

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

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

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

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

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

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

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

Пример:

  • Клиент инициирует 20-секундный длинный запрос на фоновом потоке
  • Клиент инициирует запрос B и C на переднем плане резьбы
  • запросы B и C будут посланы на сервер, который Безразлично «т обрабатывать их, пока это не будет сделано с 20-секундного длинного запроса

Но иногда:

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

Вот хронология от скрипача, демонстрирующая проблемы: (Увеличенная версия)

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

Так, Вопросы:

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

Примечания:

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

+1 Отличная планировка вопроса. –

+1

Вы когда-нибудь решали эту проблему? Если да, то как вы его решили? – DivisionByZorro

+0

Добавил самостоятельный ответ, описывающий наше окончательное «решение» –

ответ

2

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

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

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

+1

Я думаю, вы не должны отвечать самим собой, как на самом деле у нас нет ответа. Вы пытаетесь отправить сообщение об ошибке на connect.microsoft.com? – Shrike

+0

Теперь, когда я узнал немного больше о том, как все работает, я думаю, что это могло быть связано с перегрузкой ThreadPool. Если вы ставите очередь много длительных операций в threadpool, вы получите поведение, которое выглядит примерно так: –

+0

У меня такая же проблема с WSHttpBinding, и я не думаю, что это связано с перегруженным пулом потоков. Я использовал NetTcpBinding, и он неожиданно работает отлично. Я могу получить то, что вы описали, просто сделав мой первый вызов службе, спящий, одновременно пытаясь отобразить другой вызов параллельно с другого сервера. Ничто другое не может связаться с сервисом независимо от того, как настроено мое поведение службы и регулирование обслуживания. – Mike737

10

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

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

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

К сожалению, это не решило его ... Это немного изменило поведение, но теперь все запросы, похоже, резервные копии на сервере –

+0

Обновлен мой вопрос с графиком временной шкалы от fiddler, который, надеюсь, поможет –

0

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

+0

Существует , у которого есть упорядоченный атрибут ... У меня он установлен как

1

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

Это так, это звучит как this is your problem, сеанс дросселирования, что-то, что укусило меня в попку.

1

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

4

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

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

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

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

2

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

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

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

Я думаю WSHttpBinding использует параметры Wininet при выдаче запросы.

+0

Это кажется вероятным, но я давно потерял исходный код. Спасибо хоть! –

0

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

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