Подтвердить что ты не робот

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

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

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

  • Услуга, похоже, проглатывает исключение/ошибка, поэтому я не могу отлаживайте его. Как получить услугу выставить исключение, чтобы я может регистрировать или обрабатывать его?
  • Услуга попадание в неисправное состояние после это исключение проглатывается. Как Я не могу войти в сервис в неисправное состояние?
4b9b3361

Ответ 1

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

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

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

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

Ответ 3

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

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

  • Вы бросаете ошибки? или исключения? это важно (и должно быть "ошибками" ).
  • как взломать, вы можете включить отладочные сообщения об исключениях, но отключите их пожалуйста.
  • Вы "используете" объект службы? Я просто в блоге об этом точном предмете... в основном, ваш "использование" может усвоить исключение. 3 варианта:

    • не использовать "используя"
    • подкласс прокси и переопределить Dispose()
    • оберните его, как в блоге

Ответ 4

Обычно служба 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<ServiceEndpoint> 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

Ответ 5

Около 2)...

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

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

ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
    proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID);
);

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

using System;
using System.ServiceModel;

namespace Sportina.EnterpriseSystem.Client.Framework.Helpers
{
    public delegate void UseServiceDelegate<TServiceProxy>(TServiceProxy proxy);

    public static class ServiceHelper<TServiceClient, TServiceInterface> where TServiceClient : ClientBase<TServiceInterface>, new() where TServiceInterface : class
    {
        public static void Use(UseServiceDelegate<TServiceClient> 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();
            }
        }
    }
}

Ответ 6

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

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

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

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

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

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