WCF: Retry when service is in fault state.
Service Host:
using System; using System.Configuration; using System.ServiceModel; using System.ServiceModel.Activation; using System.Web.Configuration; using log4net; using System.Threading; namespace Test.Custom { public class CustomServiceHostFactory : System.ServiceModel.Activation.WebServiceHostFactory { private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { log4net.Config.XmlConfigurator.Configure(); CustomServiceHost customServiceHost = new CustomServiceHost (serviceType, baseAddresses); log.Info("Create Service Host called"); customServiceHost.incomingServiceType = serviceType; customServiceHost.incomingBaseAddresses = baseAddresses; customServiceHost.Faulted += customServiceHost.OnServiceHostFaulted; return customServiceHost; } } public class CustomServiceHost : ServiceHost { public Type incomingServiceType { get; set; } public Uri[] incomingBaseAddresses { get; set; } private int Attempts = 0; private bool isSuccess = false; private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public CustomServiceHost (Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { log.Info("CustomServiceHost constructor called"); } protected override void ApplyConfiguration() { base.ApplyConfiguration(); } public void OnServiceHostFaulted(object sender, EventArgs e) { log.Info("Host state is fault."); ICommunicationObject faultedHost = (ICommunicationObject)sender; faultedHost.Abort(); faultedHost = new ServiceHost(this.incomingServiceType, this.incomingBaseAddresses); //faultedHost.Faulted += this.OnServiceHostFaulted; log.Info("Host state is " + faultedHost.State.ToString()); if (Attempts < 5 && isSuccess == false) { Attempts++; log.Info("Retry to create server host for the" + Attempts + "time"); try { if (isSuccess == false) { Thread.Sleep(1 * 1000); } faultedHost.Open(); isSuccess = true; } catch (Exception ex) { faultedHost.Abort(); log.Info("Host state is " + faultedHost.State.ToString()); log.Info("Exception: " + ex.Message); } } } //protected override void OnFaulted() //{ // base.OnFaulted(); //} } }
1. 创建一个自定义的HostFactory,继承自WebServiceHostFactory;
2. 重载CreateServiceHost方法,并在方法内添加ServiceHost对象的Faulted的EventHandler处理;
3. 对自定义Faulted EventHandler方法根据需要加入Retry。
Service Client:
using Microsoft.ServiceBus; using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace Test.WCF.ServiceBus.Client { class Program { public static ChannelFactory<IMediaServicesManagementServiceChannel> testCF=null; static void Main(string[] args) { Retry( () => { bool flag = false; var cf = new ChannelFactory<IMediaServicesManagementServiceChannel>( new NetTcpRelayBinding(), new EndpointAddress(ServiceBusEnvironment.CreateServiceUri("sb", "***Service Bus Name***", "***Relay Name***"))); cf.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior { TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "***Service Bus Token***") }); var ch1 = cf.CreateChannel(); try { Console.WriteLine(ch1.AddNumbers(3, 4)); flag = true; } catch { ch1.Abort(); flag = false; } finally { if (ch1 != null) { ch1.Close(); } } return flag; }, 5); Console.WriteLine("Press ENTER to close"); Console.ReadLine(); } public static void Retry(Func<bool> task, int times) { bool flag = false; for (int i = 0; i < times; i++ ) { flag = task(); if(flag==true) { break; } } } } }
Referece Links:
http://msdn.microsoft.com/en-us/library/windowsazure/hh966775.aspx