我有一个不应该进入故障状态的WCF服务。如果存在异常,则应记录该异常,并且服务应继续不间断。该服务具有单向操作合同,并且正在从MSMQ中读取消息。
我的问题有两个:
答案 0 :(得分:28)
有关如何处理故障的官方文档如下:
有一个很好的状态图显示事情是如何发生的:
答案 1 :(得分:19)
在WCF跟踪(Configuring Tracing)中可以看到大多数(如果不是全部)异常,并且最好使用Service Trace Viewer查看跟踪。
显然,这不是你应该在生产环境中整天运行的东西,但无论如何它都有助于排除故障。
除此之外,请注意,根据您使用的SessionMode,单向运行可能无法真正“发射并忘记”。如果您为SessionMode.Allowed或甚至SessionMode.Required配置了服务,则单向操作将运行,就好像它根本不是一样(当在netTcpBinding上单独使用时可以观察到这一点)。坦率地说,我不知道这是否会改变您可以获得的例外类型,或者当您获得它们时。但是,在任何情况下,如果无法发送请求,您应该获得异常。 AFAIK,在服务器端成功启用时,单向“结束”。因此,在此之前(WCF框架相关)异常有一些地方(想到序列化/反序列化)。
然后,最好看到这样的框架相关异常(即使IErrorHandler因使用上述跟踪/跟踪查看器在请求/响应流中调用它而无法全部获取它们)。
答案 2 :(得分:11)
例外将导致代理错误。你不能AFAIK做很多事情:不要引起例外;-p
我有点惊讶,单向仍然导致问题,但吞咽属于 l,有3个方面:
答案 3 :(得分:9)
通常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();
积分http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf
答案 4 :(得分:7)
关于2)......
诀窍是你应该使用“using”并且应该总是在抛出异常的代理上调用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();
}
}
}
}
答案 5 :(得分:7)
我遇到一个问题,其中Channel在ReceiveTimeout异常后仍然处于故障状态。这将导致服务因后续连接而无法使用。
我为故障状态恢复服务的修复方法是处理通信渠道的故障事件:
channelFactory = new ChannelFactory<IService>(endpoint);
channelFactory.Faulted += OnChannelFaulted;
var channel = channelFactory.CreateChannel();
然后定义OnChannelFaulted:
void OnChannelFaulted(object sender, EventArgs e)
{
channelFactory.Abort();
}
注意:我通过代码运行WCF配置,而不是使用Web.config中的绑定。