2008-11-24 5 views
30

Ich habe einen WCF-Dienst, der nicht in den fehlerhaften Zustand gelangen sollte. Wenn es eine Ausnahme gibt, sollte diese protokolliert werden und der Dienst sollte ununterbrochen fortgesetzt werden. Der Dienst hat einen One-Way-Operation-Vertrag und liest Nachrichten von einem MSMQ.Wie verhindere ich, dass ein WCF-Dienst in einen fehlerhaften Zustand versetzt wird?

Meine Probleme sind zweifach:

  1. Der Dienst erscheint eine Ausnahme/Fehler zu schlucken, so bin ich zu debug es nicht in der Lage. Wie bekomme ich den Service die Ausnahme zu offenbaren, so dass ich kann loggen oder behandeln?
  2. Der Service ist tritt in einen fehlerhaften Zustand nach diese Ausnahme wird verschluckt. Wie verhindere ich, dass der Dienst in einen fehlerhaften Zustand eingibt?
+0

Hier können Sie alle Theorie http://msdn.microsoft.com/en-us/library/ms789041(v=vs.110).aspx –

Antwort

18

Die meisten, wenn Nicht alle Ausnahmen sind in der WCF-Ablaufverfolgung (Configuring Tracing) sichtbar und die Ablaufverfolgung wird am besten mit der Service Trace Viewer angezeigt.

Offensichtlich sollten Sie nicht den ganzen Tag in einer Produktionsumgebung laufen, aber es hilft trotzdem bei der Fehlersuche.

Abgesehen davon, dass oneways möglicherweise nicht als echtes "fire and forget" ausgeführt wird, abhängig vom verwendeten SessionMode. Wenn Sie Ihren Dienst für SessionMode.Allowed oder sogar SessionMode.Required konfiguriert haben, wird der oneway-Vorgang so ausgeführt, als ob er überhaupt nicht vorhanden wäre (dies kann beobachtet werden, wenn oneways über netTcpBinding verwendet wird). Um ehrlich zu sein, weiß ich jedoch nicht, ob das die Art von Ausnahmen ändert, die Sie bekommen können, oder wann Sie sie bekommen. In jedem Fall sollten Sie jedoch eine Ausnahme erhalten, wenn die Anfrage überhaupt nicht gesendet werden konnte. AFAIK, der Oneway "endet" wenn er serverseitig erfolgreich angequatscht wird. Daher gibt es bis zu diesem Zeitpunkt (bis auf WCF-Framework bezogene) Ausnahmen (Serialisierung/Deserialisierung).

Dann sind solche Framework-bezogene Ausnahmen am besten zu sehen (sogar ein IErrorHandler bekommt sie nicht alle aufgrund der Tatsache, wenn es in der Anfrage/Antwort-Flow aufgerufen wird) mit der oben genannten Trace/Traceviewer.

+0

Ich bin mit dem ähnlichen Problem konfrontiert. Ich habe den Dienst auf Produktion mit netTcpBinding mit wenigen Methoden wie IsOneway = True und SessionMode festgelegt Wenn es eine Ausnahme gibt, geht der Dienst in den Zustand Faulted. Um es funktionieren zu lassen, muss ich es neu starten. –

11

Ausnahmen werden den Proxyfehler verursachen. Sie können nicht AFAIK viel darüber tun: keine Ausnahmen; -p

Ich bin ein wenig überrascht, dass Einweg verursacht immer noch ein Problem, aber zum Schlucken in Gattungen l, gibt es 3 Aspekte:

  1. werfen Sie faults? oder Ausnahmen? Es ist wichtig (und sollte "Fehler" sein)
  2. als Hack, können Sie Debug-Ausnahme Nachrichten aktivieren - aber schalten Sie es bitte aus !!!
  3. Verwenden Sie das Serviceobjekt? Ich habe gerade blogged zu diesem genauen Thema ... im Grunde kann Ihre "Verwendung" die Ausnahme verschlucken. 3 Möglichkeiten:

    • verwenden "mit"
    • Unterklasse nicht den Proxy und außer Kraft setzen Dispose()
    • es wickeln, gemäß dem Blog
+0

Vielen Dank für die Kommentare Marc. Ich hörte auf zu benutzen, um zu versuchen, die Ausnahmen aufzuspüren, aber kein Glück. Die Business-Schicht, in der der WCF-Dienst anruft, wirft Ausnahmen, aber diese werden irgendwo verschluckt ... Mystery ... – Guy

+1

Sie könnten versuchen, zu FaultException wechseln, wo T ein veröffentlichter Fehler ist - das könnte Dinge helfen.Und beachte, dass es immer noch sehr wichtig ist, den Proxy zu schließen. einfach, dass das "Benutzen" nicht unbedingt das macht, was wir bei dieser Gelegenheit wollen. –

+0

Ich denke, nur Ausnahmen, die nicht abgefangen und durch den Dienst eingewickelt werden den Proxy, aber nicht alle Ausnahmen –

7

Über 2) ...

Der Trick ist, dass Sie „verwenden“ verwenden und sollte immer rufen Abort() auf dem Proxy, der eine Ausnahme ausgelöst hat. Der Artikel WCF Gotcha erklärt alles.

Wir verwenden die Serviceklasse, die von diesem Artikel inspiriert wurde, die Serviceaufrufe umschließt. Dies ist ein Beispielcode aus meinem Projekt:

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

Und das ist der Code von ServiceHelper, leicht von dem Artikel geändert. Bis jetzt hat es uns sehr gut gedient.

+3

Der Link zu 'WCF Gotcha' ist gebrochen, aber ich habe nicht genug Rep, um es zu bearbeiten. Hier ist der gute Link: http://old.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx. – yzorg

+0

@yzorg - Danke für den Link, ich habe gerade die Antwort aktualisiert. – LamonteCristo

6

Ich hatte ein Problem, bei dem der Kanal nach einer ReceiveTimeout-Ausnahme in einem fehlerhaften Zustand blieb. Dies würde dazu führen, dass der Dienst durch nachfolgende Verbindungen unbrauchbar gemacht wird.

Das Update den Dienst von dem fehlerhaften Zustand für mich für die Wiederherstellung war das Faulted Ereignis des Kommunikationskanals zu handhaben:

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

Dann definieren OnChannelFaulted:

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

Hinweis: Ich betreibe Die WCF-Konfiguration über Code im Vergleich zu Bindungen in Web.config.

8

Normalerweise wird der WCF-Dienst in einem ServiceHost gehostet. Wenn der WCF-Dienst fehlschlägt, besteht die einzige Möglichkeit darin, den WCF-Dienst zu beenden und einen neuen zu starten.

Der Servicehost hat einen Ereignisauslöser „Faulted“, der aktiviert wird, wenn der WCF-Dienst versagt:

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

Es ist möglich, die Ausnahme zu erhalten, den Fehler verursacht, aber es erfordert ein bisschen mehr Arbeit:

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(); 

Credits http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf

+1

Versucht dies, aber die HandleError-Methode wird nie getroffen, obwohl ich den Ereignishandler Faulted angeklickt habe. – Brent

Verwandte Themen