zoukankan      html  css  js  c++  java
  • 内部通信服务

    内部通信服务(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 oota2d.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架构师
     
  • 相关阅读:
    LDA-math-MCMC 和 Gibbs Sampling
    本地blast详解
    【shell命令】拆分、合并、排序、比较文件
    数学中竟然还有这样的定理!
    数学之美番外篇:平凡而又神奇的贝叶斯方法
    glean工具和maker工具
    Perl语言中的ig
    批量替换某个目录下所有文件里的内容
    RepeatMasker使用
    Hi-C文库制备的连接酶连接效果
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3548214.html
Copyright © 2011-2022 走看看