Как предотвратить включение службы WCF в состояние ошибки?

У меня есть служба WCF, которая не должна вводить неисправное состояние. Если есть исключение, оно должно быть зарегистрировано, и служба должна оставаться непрерывной. Услуга имеет односторонний контракт на работу и считывает сообщения из MSMQ.

Мои проблемы двоякие:

  1. Похоже, что служба проглатывает исключение / ошибку, поэтому я не могу ее отладить. Как заставить службу выставлять исключение, чтобы я мог его регистрировать или обрабатывать?
  2. Служба переходит в состояние сбоя после проглатывания этого исключения. Как предотвратить включение службы в состояние сбоя?

Большинство, если не все исключения можно увидеть в трассировке WCF ( настройка трассировки ), и трассировка лучше всего просматривается с помощью средства просмотра трассировки .

Очевидно, что это не то, что вы должны работать весь день в рабочей среде, но в любом случае это помогает в устранении неполадок.

Кроме того, обратите внимание, что в ночное время может не работать как истинный «огонь и забыть» в зависимости от используемого SessionMode. Если у вас настроен ваш сервис для SessionMode.Allowed или даже SessionMode.Required, операция oneway будет работать так, как если бы она вообще не была включена (это можно наблюдать при использовании oneways над netTcpBinding). Однако, чтобы быть откровенным, я не знаю, изменит ли это тип исключений, которые вы можете получить, или когда вы их получите. Однако в любом случае вы должны получить исключение, если запрос не может быть отправлен вообще. AFAIK, oneway «заканчивается», когда он успешно находится на стороне сервера. Таким образом, существует некоторое место для (связанных с WCF) исключений до тех пор (сериализация / десериализация приходит в голову).

Затем лучше всего встречаются такие связанные с инфраструктурой исключения (даже IErrorHandler не получает их всех из-за того, что он вызван в streamе запроса / ответа), используя вышеупомянутый трассировщик / traceviewer.

Официальная документация о том, как обращаться с ошибками, приведена здесь:

  • Обработка исключений и сбоев

  • Понимание изменений в государстве

с главной страницей в обзоре модели канала

Есть диаграмма хорошего состояния, показывающая, как все происходит:

введите описание изображения здесь

Исключения будут причиной прокси-сервера. Вы не можете многое сделать AFAIK: не вызывать исключения; -p

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

  1. вы бросаете ошибки ? или исключения? это имеет значение (и должно быть «ошибками»)
  2. как взломать, вы можете включить сообщения об исключении отладки, но отключите их!
  3. вы «используете» объект службы? Я только что написал блог по этому предмету … в основном, ваш «использование» может проглотить исключение. 3 варианта:

    • не используйте “использование”
    • подclass прокси и переопределить Dispose ()
    • оберните его, согласно блогу

Обычно служба WCF размещается в ServiceHost, если WCF-Service терпит неудачу, единственный вариант – убить службу WCF и запустить новую.

У ServiceHost есть триггер события «Faulted», который активируется при сбое службы WCF:

ServiceHost host = new ServiceHost(new Service.MyService()); host.Faulted += new EventHandler(host_faulted); host.Open(); 

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

 public class ErrorHandler : IErrorHandler { public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { } public bool HandleError(Exception error) { Console.WriteLine("exception"); return false; } } public class ErrorServiceBehavior : IServiceBehavior { public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { ErrorHandler handler = new ErrorHandler(); foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) { dispatcher.ErrorHandlers.Add(handler); } } } ServiceHost host = new ServiceHost(new Service.MyService()); host.Faulted += new EventHandler(host_faulted); host.Description.Behaviors.Add(new ErrorServiceBehavior()); host.Open(); 

Кредиты http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf

Около 2) …

Хитрость заключается в том, что вы должны использовать «использование» и всегда должны вызывать Abort () на прокси-сервере, который выбрал исключение. Статья WCF Gotcha объясняет все это.

Мы используем class обслуживания, вдохновленный этой статьей, которая обертывает вызовы служб. Это пример кода из моего проекта:

 ServiceHelper.Use( proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID); ); 

И это код ServiceHelper, слегка измененный из статьи. Пока это нам очень понравилось.

 using System; using System.ServiceModel; namespace Sportina.EnterpriseSystem.Client.Framework.Helpers { public delegate void UseServiceDelegate(TServiceProxy proxy); public static class ServiceHelper where TServiceClient : ClientBase, new() where TServiceInterface : class { public static void Use(UseServiceDelegate codeBlock) { TServiceClient proxy = null; bool success = false; try { proxy = new TServiceClient(); codeBlock(proxy); proxy.Close(); success = true; } catch (Exception ex) { Common.Logger.Log.Fatal("Service error: " + ex); throw; } finally { if (!success && proxy != null) proxy.Abort(); } } } } 

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

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

  channelFactory = new ChannelFactory(endpoint); channelFactory.Faulted += OnChannelFaulted; var channel = channelFactory.CreateChannel(); 

Затем определите OnChannelFaulted:

  void OnChannelFaulted(object sender, EventArgs e) { channelFactory.Abort(); } 

Примечание. Я запускаю конфигурацию WCF с помощью кода и используя привязки в Web.config.