2008-11-24 119 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

相关问题