.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. (т.е. остановить цикл "Принять", продолжая принимать и отправлять)
Важно, чтобы HTTP-порт хоста был закрыт, так что брандмауэр выше по потоку может направлять трафик на другую хост-систему, но существующие соединения остаются открытыми, чтобы завершить выполнение существующих вызовов метода.
Есть ли способ сделать это в WCF?
Вещи, которые я пробовал:
- ServiceHost.Close() - сразу закрывает клиентов.
- ServiceHost.ChannelDispatchers - вызов Listener.Close() для каждого - ничего не делает
- ServiceHost.ChannelDispatchers - вызов CloseInput() для каждого - сразу закрывает клиентов.
- Override ServiceHost.OnClosing() - позволяет мне задерживать Close, пока не решит, что это нормально закрыть, но в это время разрешены новые подключения.
- Удалите конечную точку, используя описанную здесь технику . Это уничтожает все.
- Запуск сетевого сниффера для наблюдения за ServiceHost.Close(). Хост просто закрывает соединение, ответ не отправляется.
Спасибо
Изменить. К сожалению, я не могу реализовать консультативный ответ на уровне приложения, который отключается системой, поскольку клиенты в этом поле уже развернуты. (Я управляю только службой, а не клиентами)
Изменить. Я использовал рефлектор Redgate, чтобы посмотреть на реализацию Microsoft ServiceHost.Close. К сожалению, он вызывает некоторые вспомогательные классы internal
, к которым мой код не может получить доступ.
Изменить. Я не нашел полного решения, которое я искал, но предложение Беньямина использовать IMessageDispatchInspector для отклонения запросов до ввода метода службы приблизилось.