2008-11-24 53 views
30

我有一個不應該進入故障狀態的WCF服務。如果發生異常,應該記錄下來,並且服務應該不中斷。該服務具有單向操作合同,正在閱讀MSMQ的消息。如何防止WCF服務進入故障狀態?

我的問題是雙重的:出現

  1. 該服務被吞嚥 異常/故障,所以我無法 調試。我如何獲得 服務以公開該異常,以便我可以登錄或處理它?
  2. 服務 在 之後進入故障狀態,此例外被吞噬。 如何防止服務進入 進入故障狀態?
+0

在這裏你可以得到所有的理論http://msdn.microsoft.com/en-us/library/ms789041(v=vs.110).aspx – 2014-02-26 16:24:48

回答

18

大多數,如果WCF Trace(Configuring Tracing)中可以看到並非所有例外情況,並且最好使用Service Trace Viewer查看跟蹤。

顯然,這不是你應該在生產環境中整天運行的東西,但它有助於解決故障。

除此之外,請注意,根據所使用的SessionMode,單向可能無法作爲真正的「火與遺忘」運行。如果您的服務配置爲SessionMode.Allowed或者甚至SessionMode.Required,那麼單向操作將運行,就好像它不是單向的(這可以在通過netTcpBinding使用單向時觀察到)。坦率地說,不過,我不知道這是否會改變你可以得到的例外類型,或者你得到它們的時候。但是,無論如何,如果請求根本無法發送,您應該會收到異常。 AFAIK,當它在服務器端成功獲得時,單向「結束」。因此,在此之前(與WCF框架相關的)異常有一些地方(想到序列化/反序列化)。

然後,使用上面提到的跟蹤/跟蹤查看器,可以很好地看到這樣的框架相關異常(即使是IErrorHandler也不會在請求/響應流中調用它時得到它們)。

+0

我面臨着類似的問題。我有服務在netTcpBinding上運行的產品有很少的方法,如IsOneway = True和SessionMode設置到Required.However當發生異常時,服務將進入Faulted狀態。要使其工作,我必須重新啓動它 – 2015-08-12 09:28:14

11

異常將代理故障。你不能做太多的事情:不要造成異常; -p

我有點驚訝,單向仍然造成問題,但吞嚥 l,有3方面:

  1. 你投擲faults?或例外?它很重要(並應該是「錯誤」)
  2. 作爲一個黑客,你可以啓用調試異常消息 - 但請關掉它!
  3. 你是「使用」服務對象嗎?我只是blogged這個確切的主題......基本上,你的「使用」可以吞噬異常。 3個選項:

    • 不要使用 「使用」
    • 子代理和重寫的Dispose()
    • 把它包起來,按照該博客
+0

感謝您的意見馬克。我停止使用嘗試和追查例外,但沒有運氣。 WCF服務調用的業務層正在拋出異常,但這些被吞噬在某處...神祕...... – Guy 2008-11-24 23:36:53

+1

您可以嘗試切換到FaultException ,其中T是已發佈的錯誤 - 這可能有所幫助。並注意關閉代理仍然非常重要;只是「使用」並不一定就是我們想要的。 – 2008-11-25 04:59:32

+0

我認爲只有沒有被服務捕獲和包裝的異常將代理服務器故障,但並非所有的異常 – 2009-06-30 12:47:16

7

約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異常後,Channel仍處於故障狀態。這將導致服務被任何後續連接渲染爲不可用。

從我的故障狀態恢復服務的修復是處理的通信信道發生故障的事件:

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

然後定義OnChannelFaulted:

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

注:我正在運行WCF配置通過代碼與使用Web.config中的綁定進行比較。

8

通常WCF服務託管在ServiceHost中,如果WCF服務失敗,那麼唯一的選擇是殺死WCF服務並啓動一個新服務。

ServiceHost的有一個事件觸發「故障」被激活時,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

相關問題