检测WCF服务是否在线(动态执行WCF服务)
在我们的系统里有多个wcf支撑。但是有的时候会莫名的停止,于是今天写了一个服务,定时去检测其他wcf服务是否在线。那么最简单的办法自然是引用其他wcf服务让vs给我们自动生成clientProxy然后一个个去调用是否正常。但是这种办法显然不是我要的。我要弄一个通用的服务检测。
方案1:
对于httpbinding的wcf服务有个最简单的检测方法:就是用httpClient去请求一下服务地址看有没有服务描述xml返回。如果有就是live不然就是服务异常关闭了。这个方法对于net.tcp绑定等不适用。
方案2:
使用反射动态生成channelProxy然后去尝试执行一个方法。当然这个方法最好不是Update等会影响到业务数据的方法,最好是query级别的方法。
正常使用ChannelFactory<T>调用wcf服务:
var channelFactory = new ChannelFactory<T>(endpoint); var proxy = this._channelFactory.CreateChannel();
proxy.Add(1,2);
很简单,我们只需要把T接口协定,endpoint节点名称,调用的方法名称,以及程序集名称或者路径提取到配置文件里就行了。然后把上面的代码转换成反射代码就行。
看一下最主要的方法吧,废话不多了。
private bool IsLive(string assemblyName, string apiServiceFullName, string endpointName, string testMethodName) { var basePath = AppDomain.CurrentDomain.BaseDirectory; Type apiType = null; var asm = Assembly.LoadFrom(basePath + "/services/" + assemblyPath); apiType = asm.GetType(apiServiceFullName); var channelType = typeof(ChannelFactory<>).MakeGenericType(apiType); try { FuncExtension.TryDo(() => { var channel = Activator.CreateInstance(channelType, endpointName); Type[] types = new Type[0]; var createChannelMethod = channelType.GetMethod("CreateChannel", types); var proxy = createChannelMethod.Invoke(channel, null); try { var testMethod = apiType.GetMethod(testMethodName); var patameterInfos = testMethod.GetParameters(); List<object> parameters = new List<object>(); foreach (var patameterInfo in patameterInfos) { var defaultValue = patameterInfo.ParameterType.IsValueType ? Activator.CreateInstance(patameterInfo.ParameterType) : null; parameters.Add(defaultValue); } testMethod.Invoke(proxy, parameters.ToArray()); } catch (Exception exc) { Logger.Error( string.Format("Try to connect wcf service error:{0}, ExceptionType:{1}", endpointName, exc.GetType()), GetType(), exc); throw; } finally { try { (proxy as ICommunicationObject).Close(); } catch { (proxy as ICommunicationObject).Abort(); } } }, 3); return true; } catch (Exception exc) { PrintWholeException(exc); return !IsHttpOrSocketException(exc); } } private void PrintWholeException(Exception exc) { Logger.Error(exc.GetType().ToString(), GetType(), exc); if (exc.InnerException != null) { PrintWholeException(exc.InnerException); } } private bool IsHttpOrSocketException(Exception exc) { if (exc is EndpointNotFoundException || exc is SocketException) { return true; } else { if (exc.InnerException != null) { return IsHttpOrSocketException(exc.InnerException); } } return false; }
其中FuncExtension.TryDo是自动尝试一个Actoin的封装,不影响理解反射的代码。
我们的目的是判断wcf是否还live,所以不要在意返回值。我们只要判断这次调用的异常是否是SocketException或者EndpointNotFindException即可。
这样,当需要监控新的wcf服务的时候只要在配置文件里添加一行协定,程序集,调用方法,endpoint的配置即可,当然协定所在的dll要复制到程序的跟目录下或者指定的文件下。
QQ群:1022985150 VX:kklldog 一起探讨学习.NET技术
作者:Agile.Zhou(kklldog)
出处:http://www.cnblogs.com/kklldog/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。