模块化与分布式
很多人都有一个误区,觉得上面那种模块化项目就是分布式系统了。其实不然,模块化本质上还是一个单体项目,只是把原来的一个个package转换成一个个module来开发而已。这个最多叫做分模块,而不是分布式。而且,模块之间往往有强依赖性,比如web-dao就必须依赖于web-model,否则连编译都通不过。
因此,模块化这个东西,我们最多就是解决了两个问题:
1.一定程度上让代码得到复用。
2.使得项目变得碎片化、积木化,方便管理和多人协作。
不过呢,很多时候,有人也会为了模块化而去模块化,比如本来一个单体项目就能解决的事情,非要拆成xxx-api,xxx-service,xxx-dao,xxx-model。看起来项目是变得高端了,但其实没有什么作用,只是徒增了系统的复杂度而已。
我第一次接触到模块化开发是在若干年前,看某小破站上黑马的淘淘商城,他就是这样模块化开发的。当时真的觉得好牛逼,没想到项目里面还能套项目,玩的是真滴花。
当时我天真的以为这大概就是分布式了吧,很多人估计跟我一样,对分布式的理解就是把一个项目拆成若干个子项目来开发,这就是分布式。
这种说法也不能说错,甚至我看到有些技术博客确实也是这么写的。
经过这些年技术的沉淀和开发,我才逐渐接触到了真正的分布式开发。
分布式架构
上面的说法其实说对了一半,分布式的概念,按照现在主流的说法,就是把一个大项目拆成若干个子项目。其中任何一个子项目,你可以运用maven聚合工程,也可以不用。然后这些子项目之间,涉及到消息传递的问题,一般是通过RPC远程调用来实现的。
RPC框架
如果是几年前你出去面试,很可能会被问到一个问题,那就是你用过什么RPC远程调用框架?
目前市面上比较常见的,有dubbo,spring系列的SpringCloud,还有重一点的webservice(soap协议)。
RPC 是一个分布式计算的 CS 模式,总是由 Client 向 Server 发出一个请求,Server 接受请求,使用者客户端提供的参数,计算完成之后将结果返回给客户端。
使用最广泛的 Spring Cloud,基于 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。
国内开源的框架中,使用比较广泛的有阿里的 Dubbo,后来捐献给了 Apache。还有腾讯的 Tars 框架,还有 Thrift 框架,也有基于 Thrift 二次开发的 RPC 框架,比如美团的 Mtthrift。
这些 RPC 大致原理基本都是一样的。
服务集成 RPC 后,服务(这里的服务就是图中的 Provider,服务提供者)启动后会通过 Register(注册)模块,把服务的唯一 ID 和 IP 地址,端口信息等注册到 RPC 框架注册中心(图中的 Registry 部分)。
当调用者(Consumer)想要调用服务的时候,通过 Provider 注册时的的服务唯一 ID 去注册中心查找在线可供调用的服务,返回一个 IP 列表(3.notify 部分)。
第三步 Consumer 根据一定的策略,比如随机 or 轮训从 Registry 返回的可用 IP 列表真正调用服务(4.invoke)。
最后是统计功能,RPC 框架都提供监控功能,监控服务健康状况,控制服务线上扩展和上下线(5.count)
Container是服务容器,常见的有Tomcat,Weblogic,Jetty。
rpc 与 http的区别
http是协议,rpc是方法,rpc的实现可能也会用到http(比如httpClient)。
http在应用层,rpc在传输层(长连接,少了三次握手,不过http2.0也可以链接复用了)
http中所使用的报文中有效字节数仅仅占约 30%,也就是70%的时间用于传输元数据废编码。当然实际情况下报文内容可能会比这个长,但是报头所占的比例也是非常可观的。而rpc仅通过序列化发送有效数据,省去了很多无效的数据,提高传输效率。 http需要可读性强,包括输入、输出,解析等。rpc就像调用方法一样调用,很简单。
soap 与 http的区别
上面我们说到,webservice也是一种常见的rpc远程调用框架,它用的是soap协议。那么soap协议与http又有上面区别呢?
分布式架构案例
分布式架构,就是把一个大项目拆成若干个子项目,然后这些子项目之间通过RPC远程调用来实现消息传递。这就是分布式架构。
举一个例子,有一个信用卡系统,因为信用卡是一个比较大型的项目,所以没可能做成一个单体项目。所以第一步,把项目拆成若干个子项目。
假设信用卡系统分为3个子系统,rpc框架采用webservice,那么每一个子系统自己即可能是服务的提供方(Server),也可能是服务的调用方(Client)。比如信用卡客服需要查询客户信息的时候,可能只需要通过webservice去远程调用核心服务系统的客户查询服务即可。
这就是分布式架构,但是,以上架构模式至少存在以下三个问题。
1.项目中服务过多,就会导致出现管理混乱的问题。
比如核心服务已经有了客户查询的服务,然后张三需要在客服系统增加一个维护客户资料的功能,但是他并不知道核心服务已经有接口能提供客户资料的CRUD操作了,于是他就自己写了service,dao,甚至自己写了个jdbc把功能实现了。(管它三七二十一,完成了需求就行)
2.项目中服务对其他系统不透明,协同开发困难
假如有一天,其他部门的某某系统需要查询信用卡的相关信息,但是不清楚信用卡这边有没有对应的接口,就得跑来问具体的负责人。一般呢,部门也会有一个word文档,记录这边系统对外的webservice接口。可是呢,谁又能保证word文档一定没问题,一定是最新的。可能张三改了某个接口,忘记更新文档了,这样的事情太正常。
3.接口调用复杂度高
我们可以提供接口供外部系统调用,这就涉及一个鉴权,监控等问题。并不是谁都能调用接口的,作为服务端,每次对接一个新系统,可能就要单独开发一套东西来用于鉴权,很麻烦。
所以,分布式架构不得不面临一个棘手的问题,那就是服务治理。
SOA面向服务架构
正因为普通分布式架构有着上面的三大难题,所以很自然的,分布式架构必须解决服务治理的问题。
还拿上面的信用卡系统举例子,所谓的服务治理,就是专门引入一个叫做ESB企业服务总线的东西,由它去注册和管理所有的webservice服务。
一个单体项目,比如信用卡核心服务系统,存在着多个webservice服务,这些服务都应该注册到ESB服务总线。
然后,其他外部系统想要调用其中的某一个接口,就需要从ESB中转,ESB需要管理这些调用方和具体的调用过程。
ESB扮演的角色就是RPC远程框架的注册中心和监控中心。
SOA 是面向服务的架构,即企业的 IT 系统是由服务组成的,也即企业的各个应用系统是由许多标准的服务件“组装”起来的,组成应用系统中的各个服务之间是一种非常松耦合的关系。
引入ESB企业服务总线后, 上面的架构就变成了这样。
这样以来,这个系统就是分布式面向服务架构。
再说明一点,分模块和分布式没多少关系,分布式系统之间是相对独立的,系统之间通过rpc远程调用来传递消息而已。而分模块的话,模块之间往往强依赖的,不可分割的,若干个模块就好像积木一样,最终组成一个单体项目。
也就说,分布式系统的每一个系统,你可以选择模块化来做,也可以不做,这是看具体需求的。
如果上图中的几个系统是模块化开发的,你就可以说,信用卡业务系统采用的是分布式面向服务架构+模块化开发。
微服务架构
上面的分布式面向服务架构,已经是现在很多大企业的主流方案了,但是依然存在一些问题。
1.以单体项目为单位,粒度太粗,项目一多难免会有一些代码重复。比如,你要做一个功能,自己直接查一下数据库就over了,可是呢另一个系统有一个接口有类似的功能。用是能用,但是你去调用的话,还得转换一下才行,很麻烦。而且,因为这个功能并非必要,你没法让对方系统因为你要做的这个需求,去新增或者修改接口。这就是粒度太粗导致的问题。
2.SOA现在用的rpc框架太重,一般还是用webservice,因为用的是xml传输,效率肯定会慢一点。
于是,就有了微服务架构。
微服务架构是分布式面向服务架构的一个分支,本身也属于分布式面向服务架构。
SOA 和微服务架构的差别
1.更轻了,只关注http+json数据传输,也更快了。
2.粒度更细了,原子单位是一组强相关的接口集合,微服务通常是 单用途 的服务,它们可以非常非常好地完成一件事情。
3.微服务去中心化,去掉ESB企业总线。微服务不再强调传统SOA架构里面比较重的ESB企业服务总线,同时SOA的思想进入到单个业务系统内部实现真正的组件化.
4.Docker容器技术的出现,为微服务提供了更便利的条件,比如更小的部署单元,每个服务可以通过类似Node或者Spring Boot等技术跑在自己的进程中。
5.SOA注重的是系统集成方面,而微服务关注的是完全分离。因此微服务的系统是弱相关,可独立运行的。
总结一下,并不能说微服务架构就比SOA架构高级,对于面向系统集成的大型项目,还是适合用SOA。而对于那些只有http轻量级协议传输的短平快项目,就适合用微服务架构。
微服务比较考验架构师的水准,如果拆的不好反而影响开发效率。我就见过一个小项目结果硬是拆了几百个服务的情况,其中很多服务的代码都是高度重复的。这就是典型的为了用微服务而去搞微服务,最终得不偿失。