检测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要复制到程序的跟目录下或者指定的文件下。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

事件(Event),绝大多数内存泄漏(Memory Leak)的元凶[上篇]

最近这两天一直在忙着为一个项目检查内存泄漏(Memory Leak)的问题,对相关的知识进行了一下简单的学习和探索,其间也有了一些粗浅的经验积累,今天特意写一篇...

2506
来自专栏jeremy的技术点滴

开发小技巧备忘

3407
来自专栏逸鹏说道

C#注册表情缘

记得当时刚接触C#的时候,喜欢编写各种小软件,而注册表系列和网络系列被当时的我认为大牛的必备技能。直到我研究注册表前一天我都感觉他是那么的高深。 今天正好有空,...

3438
来自专栏.NET开发那点事

使用Microsoft Fakes进行单元测试(2)

接上一篇使用Microsoft Fakes进行单元测试(1) 下面进行Shim的演示。 2.使用Shim替换静态方法 假设我们需要一个工具方法用来格式化当前时...

2209
来自专栏向治洪

android-async-http框架源码分析

async-http使用地址 android-async-http仓库:git clone https://github.com/loopj/android...

2355
来自专栏跟着阿笨一起玩NET

VS2010在C#头文件中添加文件注释的方法

1.VS2010 中找到安装盘符(本人安装目录在D盘,所以以D盘为例)D:\Program Files (x86)\Microsoft Visual Studi...

1181
来自专栏NetCore

ADO.NET 2.0 中的新增 DataSet 功能

ADO.NET 2.0 中的新增 DataSet 功能 发布日期: 1/13/2005 | 更新日期: 1/13/2005 Jackie Goldstein ...

19210
来自专栏技术小讲堂

ASP.NET AJAX(4)__客户端访问WebService服务器端释放WebService方法客户端访问WebService客户端访问PageMethod错误处理复杂数据类型使用基础客户端代理的

服务器端释放WebService方法 编写一个普通的WebService 为WebService类添加自定义的属性标记__ScriptServiceAttrib...

2877
来自专栏张善友的专栏

自定义Unity对象生命周期管理集成ADO.NET Entity Framework

在Unity中,从Unity 取得的实例为 Transient。如果你希望使用多线程方式,就需要在组成时使用lifecycle参数,这时候取出的组件就不再是同一...

3558
来自专栏码农阿宇

.Net Core中利用TPL(任务并行库)构建Pipeline处理Dataflow

在学习的过程中,看一些一线的技术文档很吃力,而且考虑到国内那些技术牛人英语都不差的,要向他们看齐,所以每天下班都在疯狂地背单词,博客有些日子没有更新了,见谅见谅...

2521

扫码关注云+社区

领取腾讯云代金券