C# 如何防止WCF服务进入故障状态?
我有一个WCF服务不应进入故障状态。如果出现异常,应记录该异常,并且服务应不间断地继续。该服务具有单向操作合约,正在从MSMQ读取消息 我的问题有两个:C# 如何防止WCF服务进入故障状态?,c#,.net,wcf,msmq,C#,.net,Wcf,Msmq,我有一个WCF服务不应进入故障状态。如果出现异常,应记录该异常,并且服务应不间断地继续。该服务具有单向操作合约,正在从MSMQ读取消息 我的问题有两个: 这项服务似乎难以接受 异常/故障,因此我无法 调试它。我怎样得到服务 公开异常,以便 你能记录或处理它吗 服务是 之后进入故障状态 这个例外被接受了。怎么办 我阻止服务进入 进入故障状态 异常将导致代理出错。对此你无能为力:不要引起异常-p 我有点惊讶单向仍然会引起问题,但是对于一般的吞咽,有三个方面: 你在扔吗?还是例外?这很重要(应该是“错
异常将导致代理出错。对此你无能为力:不要引起异常-p 我有点惊讶单向仍然会引起问题,但是对于一般的吞咽,有三个方面:
- 不要使用“使用”
- 子类化代理并重写Dispose()
- 按照博客的说法,把它包装起来
大多数(如果不是所有的话)异常都可以在WCF跟踪()中看到,最好使用 显然,这不是您应该在生产环境中全天运行的东西,但它有助于故障排除 除此之外,请注意,根据您使用的会话模式,oneways可能不会作为真正的“fire and forget”运行。如果您为SessionMode.Allowed甚至SessionMode.Required配置了服务,则单向操作将以完全不是单向的方式运行(在netTcpBinding上使用单向时可以观察到这一点)。但是,坦率地说,我不知道这是否会改变您可以获得的异常类型,或者何时获得它们。但是,在任何情况下,如果请求根本无法发送,您都应该得到一个异常。好吧,当它在服务器端被成功地请求时,单向“结束”。因此,在此之前,存在(与WCF框架相关的)异常(想到序列化/反序列化) 然后,使用上面提到的trace/traceviewer可以最好地看到这种与框架相关的异常(由于在请求/响应流中调用IErrorHandler的事实,即使IErrorHandler也无法获得所有异常) 诀窍是您应该使用“using”,并且应该始终对引发异常的代理调用Abort()。这篇文章解释了这一切 我们使用的服务类的灵感来自于包装服务调用的那篇文章。这是我的项目中的示例代码:
ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID);
);
serviceheloper.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();
}
}
}
}
使用系统;
使用System.ServiceModel;
命名空间Sportina.EnterpriseSystem.Client.Framework.Helpers
{
公共委托无效UseServiceDelegate(TServiceProxy代理);
公共静态类ServiceHelper,其中TServiceClient:ClientBase,new(),其中TServiceInterface:class
{
公共静态无效使用(UseServiceDelegate代码块)
{
TServiceClient proxy=null;
布尔成功=假;
尝试
{
proxy=新的TServiceClient();
代码块(代理);
proxy.Close();
成功=真实;
}
捕获(例外情况除外)
{
Common.Logger.Log.Fatal(“服务错误:+ex”);
投掷;
}
最后
{
如果(!success&&proxy!=null)
proxy.Abort();
}
}
}
}
我遇到了一个问题,在接收超时异常后,通道仍处于故障状态。这将导致任何后续连接都无法使用该服务
对我来说,从故障状态恢复服务的修复方法是处理通信通道的故障事件:
channelFactory = new ChannelFactory<IService>(endpoint);
channelFactory.Faulted += OnChannelFaulted;
var channel = channelFactory.CreateChannel();
注意:我是通过代码运行WCF配置,而不是在Web.config中使用绑定。通常WCF服务托管在ServiceHost中,如果WCF服务失败,则唯一的选择是终止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();
公共类ErrorHandler:IErrorHandler
{
public void providefaulture(异常错误,消息版本,ref消息错误)
{
}
公共布尔句柄错误(异常错误)
{
控制台写入线(“例外”);
返回false;
}
}
公共类ErrorServiceBehavior:IServiceBehavior
{
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
public void AddBindingParameters(ServiceDescription ServiceDescription、ServiceHostBase ServiceHostBase、集合终结点、BindingParameterCollection bindingParameters)
{
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
ErrorHandler=新的ErrorHandler();
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher)
{
dispatcher.ErrorHandlers.Add(处理程序);
}
}
}
ServiceHost主机=新的ServiceHost(new Service.MyService());
host.Faulted+=新的EventHandler(host\u Faulted);
host.Description.Behaviors.Add(新的ErrorServiceBehavior());
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();