说说面向服务的体系架构SOA

序言

在.Net的世界中,一说起SOA,你们想到的应该是Web Service,WCF,还有人或许也会在.NET MVC中的Web API上作上标记,而后泛泛其谈!nginx

的确,微软的这些技术也确实推进着面向服务的世界发展,固然除了微软还有不少面向服务的开源技术,甚至在某些方面比微软作的更加优秀。那么什么是面向服务,面向服务的存在是为了解决什么问题呢?web

说说SOA面向服务

SOA是由Garnter在1996年提出的一个概念,旨在让软件变的有弹性,可以迅速响应业务的需求,实现实时企业。基本理念是让全部信息系统中须要整合的业务使用服务和接口联系起来,接口中立,与开发平台和编程语言无关。这也使得异构信息系统变的可开发,“信息孤岛”,重复造轮子等问题在SOA的体系架构下不攻自破。算法

简单通俗的说就是,SOA是不一样业务创建不一样的服务,服务之间的能够数据交互粗粒度的服务接口分级,这样松散耦合提升服务的重用性,也让业务逻辑变的可组合,而且每一个服务能够根据使用状况作出合理的分布式部署,从而让服务变的规范,高性能,高可用。sql

那么接下来咱们首先来看下微软在这方面作啦哪些贡献,以及软件开发是怎样的一个变化历程。apache

代码复用技术的发展
编程

面向过程(应用内/过程级复用)---->面向对象(应用内/类级复用)--->面向组件(应用内/组件级复用)--->分布式组件(应用间/组件级复用)---->面向服务(应用间/服务级复用)json

微软面向服务提供的技术api

那么针对上面的一张图,作一个简短的说明,首先是Tcp与Http协议的比较,这两个协议各有所长:缓存

基于TCP协议:可以减小网络传输字节数,下降网路开销,效率高,可是实现复杂,且因为协议和标准不一样,难以进行跨平台,和企业间的便捷通讯,而且当服务愈来愈多的时候,负载聚恒策略,服务地址管理和配置都会变得复杂和繁琐,目前也没有很好的开源支持。tomcat

基于Http协议:那么他相对于Tcp来讲,首先他是构建在Tcp/Ip协议之上,效率相对于tcp要低,传输字节也要比tcp多,因此他传输占用的时间会长,固然咱们也能使用一些gzip数据压缩等对数据压缩或者相似于Hessain,Thrift等等传输2进制数据流,减小数据传输量缩减与TCP的差距,固然HTTP也是有不少本身的优势,好比他的存在天生就能够解决异构调用的问题,还有处理处理大流量高并发的状况下不少成熟开源的解决方案想iis,nginx,tomcat,apache等。

因此对上面两种协议的对比,各有所长各有其短,你们各取所需就好啦。

各类数据序列化对比

数据传输协议的取舍,也是根据本身的需求,在.net的世界中我认为应该json跟xml应该是被你们普遍使用的。那么还有那些对象序列化常见于网络传输呢,Hessian,thrift也是比较经常使用的。网上也有不少对比,我从网上拿下来的就有,其实以下图,仅供参考。

.Net使用Hessian进行序列化,实现基于Http协议的RPC

针对上述的测试图,咱们能够看出Hessian也是一个不错的选择,那么在这里我来写一个.Net mvc中使用hessian的小例子,供你们学习参考,也体验下RPC风格的Hessian有多便捷。

同时hessian也支持N多语言,他采用二进制格式传输的服务框架,据测试效率是soap传输的10倍。因此更轻量快速,官网地址:http://hessian.caucho.com/

那么咱们摒弃类微软的webservice,wcf,webapi等框架,使用啦开源的hessian,来实施服务之间的远程调用。

一、服务端

引用Hessiancsharp.dll

实现类继承CHessianHandler类,引用命名空间using hessiancsharp.server,同时实现Iserverice接口,Iservice是对外提供的。

 public class Service : CHessianHandler, IService
    {
        private readonly string _connStr = ConfigurationManager.ConnectionStrings["ConnectionString_write"].ConnectionString;

        #region IService 成员

        public string ServerName { get { return ConfigurationManager.AppSettings["ServerName"]; } }
        public List<D_DriverInfo> GetDriverInfo()
        {
            try
            {
                using (DbConnection conn = new SqlConnection(_connStr))
                {
                    conn.Open();
                    string sql = "SELECT TOP 10 * FROM dbo.D_DriverInfo";

                    return conn.Query<D_DriverInfo>(sql).ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }

        }

        public D_DriverInfo GetDriverInfoByUcode(string ucode)
        {
            try
            {
                using (DbConnection conn = new SqlConnection(_connStr))
                {
                    conn.Open();
                    string sql = "SELECT * FROM dbo.D_DriverInfo where Ucode = @Ucode";

                    return conn.QuerySingle<D_DriverInfo>(sql, new { Ucode = ucode });
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        #endregion
    }
View Code
 public interface IService
    {
        string ServerName { get;  }
        List<D_DriverInfo> GetDriverInfo();
        D_DriverInfo GetDriverInfoByUcode(string ucode);
    }
 <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <httpHandlers>
      <add verb="*" path="HessianServiceMvc.IService.hessian" type="HessianServiceMvc.Service, HessianServiceMvc" />
    </httpHandlers>
  </system.web>
   <system.webServer>
        <handlers>        
            <add name="MvcHessianService" path="*.hessian" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
        </handlers>
    </system.webServer>
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{hessian}.hessian/{*pathInfo}");
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }      

二、客户端使用服务

引用Hessiancsharp.dll,把服务端的接口写下来,不用实现,远程用服务实现服务调用方的方法。

            CHessianProxyFactory factory = new CHessianProxyFactory();
            string url = "http://172.18.5.61:9020/HessianService.hessian";//修改成你的server端地址
            IService test = (IService)factory.Create(typeof(IService), url);
            object result = test.GetDriverInfo();
            List<D_DriverInfo> s = HClient.RunClient<IService>().GetDriverInfo();
            return Json(s, JsonRequestBehavior.AllowGet);

Note,不妨试试,感觉下使用起来方便快捷不?

说说服务路由,服务负载均衡与服务去中心化结构

首先若是你的业务量不是很大,服务都是单台部署,那么你的服务地址能够硬编码到你的项目中,可是若是你的服务单台扛不住流量并发甚至性能特别差,那么咱们就须要分布式部署咱们的服务。

最初咱们是这样子实现的

不论你走的是老式的Esb,仍是一些代理服务器,都是先把请求打到另一台服务器,而后给你转接给服务提供方。

如今咱们是怎么实现的呢

Note:Soa架构会提供一个Client.dll,给到调用方,让调用方没必要关系你的传输协议怎么实现,负载算法怎么实现,这均可以配置出来。而后服务每上线一台机器,都会自动注册接口地址等信息到服务配置中心,服务监测系统也会及时的捕捉到各个服务的上下线状态,而后更新存储起来,Client内置有负载均衡及缓存功能,根据监测系统提供的数据,客户端配置的信息,本身发现最优的服务给到客户端。然而这一切都放生在客户端。没有第三方代理服务器出现。

由上述两张图片,也能够得出一个信息,咱们先假定使用图一,若是代理服务器或是请求路由分发器之类的东西挂了,那全部的服务就不能用啦,还有中间转接一次,性能也不如第二种好,第二种没有中心化结构,我感受仍是挺叼的,不写了,这篇就到这里吧。

总结

比较浅,也比较笼统,若是有什么不妥之处,还望提出,同时也欢迎加入左上方群,咱们一块儿交流学习。

相关文章
相关标签/搜索