.NET 3.5, VS2008, служба WCF с использованием BasicHttpBinding
У меня есть служба WCF, размещенная в службе Windows. Когда служба Windows закрывается из-за обновлений, планового обслуживания и т. Д., Мне нужно изящно завершить свою службу WCF. Служба WCF имеет методы, выполнение которых может занять до нескольких секунд, а типичный объем составляет 2-5 вызовов метода в секунду. Мне нужно завершить службу WCF таким образом, чтобы можно было завершить любые ранее вызванные методы, при этом отказывая в новых вызовах. Таким образом, я могу достигнуть спокойного состояния через ~ 5-10 секунд, а затем завершить цикл выключения моей службы Windows.
Вызов ServiceHost.Close кажется правильным подходом, но он сразу закрывает клиентские соединения, не дожидаясь завершения каких-либо методов. Моя служба WCF завершает свой метод, но некому отправить ответ, потому что клиент уже был отключен. Это решение, предложенное этим вопросом .
Вот последовательность событий:
- Клиент вызывает метод в службе, используя сгенерированный VS прокси-класс
- Служба начинает выполнение метода службы
- Сервис получает запрос на отключение
- Служба вызывает ServiceHost.Close (или BeginClose)
- Клиент отключен и получает исключение System.ServiceModel.CommunicationException
- Сервис завершает метод обслуживания.
- В конце концов служба обнаруживает, что ей больше не нужно выполнять (через логику приложения), и завершает работу.
Мне нужно, чтобы клиентские соединения оставались открытыми, чтобы клиенты знали, что их методы обслуживания завершены успешно. Сейчас они просто получают закрытое соединение и не знают, успешно ли завершен метод обслуживания. До использования WCF я использовал сокеты и мог сделать это, управляя Socket напрямую. (то есть остановите цикл Accept, продолжая получать и отправлять)
Важно, чтобы HTTP-порт хоста был закрыт, чтобы вышестоящий брандмауэр мог направлять трафик на другую хост-систему, но существующие соединения оставались открытыми, чтобы позволить существующим вызовам методов завершиться.
Есть ли способ сделать это в WCF?
Вещи, которые я пробовал:
- ServiceHost.Close () - сразу закрывает клиентов
- ServiceHost.ChannelDispatchers - вызывать Listener.Close () для каждого - кажется, ничего не делает
- ServiceHost.ChannelDispatchers - вызывать CloseInput () для каждого - сразу же закрывать клиентов
- Переопределить ServiceHost.OnClosing () - позволяет мне отложить закрытие до тех пор, пока я не решу, что все в порядке, но в это время разрешены новые подключения
- Удалите конечную точку, используя метод , описанный здесь . Это уничтожает все.
- Запуск сетевого анализатора для наблюдения ServiceHost.Close (). Хост просто закрывает соединение, ответ не отправляется.
Спасибо
Редактировать : К сожалению, я не могу реализовать консультативный ответ на уровне приложения о том, что система закрывается, потому что клиенты на местах уже развернуты. (Я контролирую только службу, а не клиентов)
Редактировать : Я использовал отражатель Redgate, чтобы посмотреть на реализацию Microsoft ServiceHost.Close. К сожалению, он вызывает некоторые internal
вспомогательные классы, к которым мой код не может получить доступ.
Редактировать : Я не нашел полного решения, которое искал, но предложение Бенджамина использовать IMessageDispatchInspector для отклонения запросов до входа в сервисный метод было ближе всего.