У меня есть клиентское/серверное приложение 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-секундного завершения (это редко)
Здесь показана временная шкала от скрипача, демонстрирующая проблему: (нажмите для увеличения)
Как вы можете видеть, все запросы выполняются на сервере. Как только 20-секундный запрос завершается, все ответы наступают, но обратите внимание, что есть некоторые запросы, которые не получают поддержки...
Итак, Вопросы:
- Что, черт возьми, происходит здесь? Почему он работает нормально, используя
NetTcpBinding
и не работает с помощьюWSHttpBinding
? - Почему несовместимое поведение?
- Что я могу сделать, чтобы исправить это?
Примечания:
- Он не блокируется на сервере. Я установил точки останова и использовал
!syncblk
, и он постоянно сообщает, что блокировки не хранятся. - Это не моя нить (NetTcpBinding не должно работать иначе)
- У меня
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />
установлен на сервере app.config - 20-секундный вызов просто ждет таймера, он не разбивает процессор, диск или сеть.
- Я бы предпочел решение, которое не включало бы повторное архивирование приложения для использования асинхронных вызовов... это большая группа устаревшего кода, и я действительно не хочу возиться с вещами, которые я не понимаю.