你的位置:首页 > ASP.net教程

[ASP.net教程]检测WCF服务是否在线(动态执行WCF服务)


  在我们的系统里有多个wcf支撑。但是有的时候会莫名的停止,于是今天写了一个服务,定时去检测其他wcf服务是否在线。那么最简单的办法自然是引用其他wcf服务让vs给我们自动生成clientProxy然后一个个去调用是否正常。但是这种办法显然不是我要的。我要弄一个通用的服务检测。

  方案1:

  对于httpbinding的wcf服务有个最简单的检测方法:就是用httpClient去请求一下服务地址看有没有服务描述

  方案2:

  适用反射动态生成channelProxy然后去尝试执行一个方法。当然这个方法最好不是Update等会影响到业务数据的方法,最好是query级别的方法。

  正常适用反射调用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要复制到程序的跟目录下或者指定的文件下。