首页 > 其他 > 详细

内部通信服务(WCF)

时间:2014-02-13 21:13:51      阅读:419      评论:0      收藏:0      [点我收藏+]

WCF,很好,却又麻烦,很多时候不想用WCF的原因就是:用这个真麻烦...

麻烦的地方,比如:

  • 一堆一堆的服务配置,散落在一个一个的folder下,更新系统时容易出错
  • 客户端除了要知道WCF Contract外,还要知道服务Provider所在位置

所以想了个办法来简化这些,主要思路是:

  • 加入Internal Communication Service,简称ICS。用来插入自定义的中间层
  • 编写一个Service Locator Service,用来将WCF服务提供者信息抽取统一保存,如:url, endpoint类型,做到wcf服务提供者位置无关性

完成后,WCF客户端(包括WCF服务内部调用了其他WCF服务的服务...)调用代码会变成如下方式:

bubuko.com,布布扣
//不支持事务的调用方式
IUser userSrv = ICSFactory.Create<IUser>();
var result = userSrv.GetUserName("1", "2", "3");
ICSFactory.Close(userSrv);



//支持事务的调用方式
string result = string.Empty;
using (TransactionScope ts = new TransactionScope())
{
      IUser userSrv = ICSFactory.Create<IUser>();
      IAdmin adminSrv = ICSFactory.Create<IAdmin>();

      result = userSrv.GetUserName("1", "2", "3");
      result = adminSrv.CheckPermission(100).ToString();

      ts.Complete();

      ICSFactory.Close(userSrv);
      ICSFactory.Close(adminSrv);
}
bubuko.com,布布扣

WCF客户端的配置信息去哪了呢? A:在appSetting中,有个key,用来表示服务配置信息文件所在路径,如:\\fs\root\a2d.service.config,配置文件如下:

bubuko.com,布布扣
<?xml version="1.0" encoding="utf-8" ?>
<A2D>
    <ServiceLocator>
        <Service ContractNamespace="DEsbInterface" Contract="IUser">
            <Url EndpointType="Tcp">net.tcp://192.168.1.100:9999/usersrv</Url>
        </Service>
        <Service ContractNamespace="DEsbInterface" Contract="IAdmin">
            <Url EndpointType="Tcp">net.tcp://192.168.1.100:9998/adminsrv</Url>
        </Service>
    </ServiceLocator>
</A2D>
bubuko.com,布布扣

 

如果调用WCF服务的客户端只有一个程序,就没多大用了,但是如果有很多客户端程序,那就有用了,如下场景:

bubuko.com,布布扣

 4台server都作为客户端进行WCF服务的调用

ICS原理:

在本例中,ICS其实就是ICSFactory,用来建立WCF服务代理,通过代码方式加入binding、address、transaction信息,底层调用的是ChannelFactory来建立通信,代码如下:

bubuko.com,布布扣
public class ICSFactory
    {
        /// <summary>
        /// 创建WCF服务代理对象
        /// </summary>
        /// <typeparam name="T">WCF的Contract类型</typeparam>
        /// <returns></returns>
        public static T Create<T>()
        {
            string contractNamespace = typeof(T).Namespace;
            string contract = typeof(T).Name;

            //根据WCF Contract信息找到相应的位置信息
            Location location = ServiceLocator.Locate(contractNamespace, contract);

            //生成绑定信息
            NetTcpBinding binding = new NetTcpBinding();
            binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            binding.Security.Mode = SecurityMode.None;
            binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

            //事务设置
            binding.TransactionFlow = true;
            binding.TransactionProtocol = TransactionProtocol.OleTransactions;

            //地址信息
            EndpointAddress address = new EndpointAddress(location.Url);

            //建立信道
            T broker=ChannelFactory<T>.CreateChannel(binding, address);

            //返回代理对象
            return broker;
        }

        /// <summary>
        /// Dispose代理对象
        /// </summary>
        /// <param name="broker"></param>
        public static void Close(object broker)
        {
            if (broker == null)
                return;

            IDisposable disposable = broker as IDisposable;
            if (disposable == null)
                return;

            disposable.Dispose();
        }
    }
bubuko.com,布布扣

 

 

Service Locator Service原理:

也就是ServiceLocator.Locate函数。

程序启动时会根据配置读取config文件的xml到内存对象中:Service、Url。具体代码略。

Locate函数的代码如下:

bubuko.com,布布扣
        /// <summary>
        /// 根据Contract的命名空间及Contract名找到服务的真实地址信息
        /// </summary>
        /// <param name="contractNamespace"></param>
        /// <param name="contract"></param>
        /// <returns></returns>
        public static Location Locate(string contractNamespace, string contract)
        {
            Service srv=null;

            string key = string.Format("{0}.{1}", contractNamespace, contract);
            if (!serviceCache.ContainsKey(key))
            {
                srv = FindService(contractNamespace, contract, srv);
                serviceCache[key] = srv;
            }
            else
            { 
                srv=serviceCache[key];
            }
            if(srv.Urls==null||srv.Urls.Count==0)
                throw new Exception(string.Format("Service‘ url not found [{0}.{1}]", contractNamespace, contract));

            Url url=srv.Urls.First();

            Location location = new Location();
            location.EndpointType = url.EndpointType;
            location.Url = url.ReferenceUrl;return location;
        }

        private static Service FindService(string contractNamespace, string contract, Service srv)
        {
            List<Service> matchedServices = LocatorServiceConfiguration.Services.Where(t =>
                    t.Contract.CompareTo(contract) == 0
                    &&
                    t.ContractNamespace.CompareTo(contractNamespace) == 0
            ).ToList();

            if (matchedServices == null || matchedServices.Count == 0)
                throw new Exception(string.Format("Service not found [{0}.{1}]", contractNamespace, contract));

            srv = matchedServices.First();
            return srv;
        }
bubuko.com,布布扣

内部通信服务(WCF)

原文:http://www.cnblogs.com/aarond/p/WCF.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!