内部通信服务

内部通信服务(WCF)

 

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

麻烦的地方,比如:

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

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

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

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

复制代码
//不支持事务的调用方式

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);

}
复制代码

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

复制代码
<?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>
复制代码

 

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

内部通信服务

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

ICS原理:

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

复制代码
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();

        }

    }
复制代码

 

 

Service Locator Service原理:

也就是ServiceLocator.Locate函数。

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

Locate函数的代码如下:

复制代码
        /// <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;

        }
复制代码
自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
A2D科技,服务社会。
A2D Framework(Alpha)
  • 1. Cache System(本地缓存与分布式缓存共存、支持Memcache和Redis、支持贴标签形式(类似Spring 3.x的Cache形式))
  • 2. Event System(本地事件与分布式事件分发)
  • 3. IoC(自动匹配功能,实例数量限制功能)
  • 4. Sql Dispatcher System(支持ADO.NET及EF)
  • 5. Session System(分布式Session系统)
  • 6. 分布式Command Bus(MSMQ实现,解决4M限制,支持Session的读取)
  • 7. 规则引擎

QQ群:283016070,真材实料的.NET架构师
 
分类:  A2D Framework架构可扩展

你可能感兴趣的:(通信)