Spring Cloud系列(一)微服务架构

什么是微服务?

       微服务实际上是一种系统架构上的设计风格,它的主旨是将一个复杂独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间通过RESTFul API进行通信协作。被拆分的各个小型服务都是围绕某一个耦合度较高的功能或者业务中的一个模块来进行构建的。每一个小型服务都维护自身的数据存储,业务开发,测试以及可以独立部署运行。因为微服务之间使用轻量级通信机制,所以各个小型服务可以使用不同的语言开发。

单体架构带来的问题

       在以往传统的企业系统架构中,我们往往会创建一个单体项目,一个单体项目在早期由于系统较小,业务不是很复杂,所以运行良好,开发部署也很方便,但是随着业务越来越复杂,导致单体项目越来越臃肿难以开发和维护,所以会带来以下问题:

1.复杂性逐渐变高

       由于各个模块之间区别比较模糊,逻辑比较混乱,代码越多复杂性越高,越难解决遇到的问题。

2.技术债务逐渐上升

       公司的人员流动是再正常不过的事情,有的员工在离职之前,疏于代码质量的自我管束,导致留下来很多坑,由于单体项目代码量庞大的惊人,留下的坑很难被发觉,这就给新来的员工带来很大的烦恼,人员流动越大所留下的坑越多,也就是所谓的技术债务越来越多。

3.部署速度逐渐变慢

       单体架构模块非常多,代码量非常庞大,导致部署项目所花费的时间越来越多。

4.阻碍技术创新

       比如以前的某个项目使用struts2写的,由于各个模块之间有着千丝万缕的联系,代码量大,逻辑不够清楚,如果现在想用spring mvc来重构这个项目将是非常困难的,付出的成本将非常大,所以更多的时候公司不得不硬着头皮继续使用老的struts架构,这就阻碍了技术的创新。

微服务与单体架构的区别

1.单体架构所有的模块全都耦合在一块,代码量大,维护困难,微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。

2.单体架构所有的模块都共用一个数据库,存储方式比较单一,微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。一方面,这种做法与企业级数据库模型的想法相悖,此外,它经常导致部分数据冗余,然而如果你想在微服务中受益,每一个服务都应该有自己的数据库模式,因为它能实现松耦合。

3.单体架构所有的模块开发所使用的技术一样,微服务每个模块都可以使用不同的开发技术,开发模式更灵活。

微服务的本质

       微服务的目的就是有效的拆分应用,实现敏捷开发和部署。让每个服务内部更加内聚,服务与服务之间松耦合。

      拆分的原则

       拆分的大原则是当一块业务不依赖或极少依赖其它服务,有独立的业务语义,为超过2个的其他服务或客户端提供数据,那么它就应该被拆分成一个独立的服务模块。如果服务的粒度划分的过粗,那就回到了单体式的老路;如果过细,那服务间调用的开销就变得不可忽视了,管理难度也会指数级增加。目前为止还没有一个可以称之为服务边界划分的标准,只能根据不同的业务系统加以调节。

微服务设计原则

1.单一职责原则
       意思是每个微服务只需要实现自己的业务逻辑就可以了,比如订单管理模块,它只需要处理订单的业务逻辑就可以了,其它的不必考虑。

2.服务自治原则
       意思是每个微服务从开发、测试、运维等都是独立的,包括存储的数据库也都是独立的,自己就有一套完整的流程,我们完全可以把它当成一个项目来对待。不必依赖于其它模块。

3.轻量级通信原则
       首先是通信的语言非常的轻量,第二,该通信方式需要是跨语言、跨平台的,之所以要跨平台、跨语言就是为了让每个微服务都有足够的独立性,可以不受技术的钳制。

4.接口明确原则

       由于微服务之间可能存在着调用关系,为了尽量避免以后由于某个微服务的接口变化而导致其它微服务都做调整,在设计之初就要考虑到所有情况,让接口尽量做的更通用,更灵活,从而尽量避免其它模块也做调整。

微服务的特性和优缺点

1.特性

①每个微服务可独立运行在自己的进程里;

②一系列独立运行的微服务共同构建起了整个系统;

③每个服务为独立的业务开发,一个微服务一般完成某个特定的功能,比如:订单管理,用户管理等;

④微服务之间通过一些轻量级的通信机制进行通信,例如通过REST API或者RPC的方式进行调用。

2.优点

①易于开发和维护

      由于微服务单个模块就相当于一个项目,开发这个模块我们就只需关心这个模块的逻辑即可,代码量和逻辑复杂度都会降低,从而易于开发和维护。

②启动较快

       这是相对单个微服务来讲的,相比于启动单体架构的整个项目,启动某个模块的服务速度明显是要快很多的。

③局部修改容易部署

       在开发中发现了一个问题,如果是单体架构的话,我们就需要重新发布并启动整个项目,非常耗时间,但是微服务则不同,哪个模块出现了bug我们只需要解决那个模块的bug就可以了,解决完bug之后,我们只需要重启这个模块的服务即可,部署相对简单,不必重启整个项目从而大大节约时间。

④技术栈不受限

       各个小型服务可以选择不同的开发语言,比如订单服务用java开发,库存服务用c开发,只需要彼此可以用RESTFul API通信即可。

3.缺点

①运维要求较高

       对于单体架构来讲,我们只需要维护好这一个项目就可以了,但是对于微服务架构来讲,由于项目是由多个微服务构成的,每个模块出现问题都会造成整个项目运行出现异常,想要知道是哪个模块造成的问题往往是不容易的,因为我们无法一步一步通过debug的方式来跟踪,这就对运维人员提出了很高的要求。

②分布式的复杂性

        对于单体架构来讲,我们可以不使用分布式,但是对于微服务架构来说,分布式几乎是必会用的技术,由于分布式本身的复杂性,导致微服务架构也变得复杂起来。所以分布式环境的问题都将是微服务架构需要考虑的问题,如网络延迟、分布式事物、session共享、异步通知、容错设计等。

③接口调整成本高

       虽然我们拆分了服务,但业务逻辑上的依赖仍然存在,我们只是让单体架构中的嵌入式依赖变成了服务间的通信依赖,如果我们对接口进行了修改,那么所有依赖它的微服务可能都需要调整,这就增加了接口调整的成本,我们需要更加完善的接口和版本管理。

④重复劳动

       对于单体架构来讲,如果某段业务被多个模块所共同使用,我们便可以抽象成一个工具类,被所有模块直接调用,但是微服务却无法这样做,因为这个微服务的工具类是不能被其它微服务所直接调用的,从而我们便不得不在每个微服务上都建这么一个工具类,从而导致代码的重复。

常用的微服务框架

1.Spring Cloud:http://projects.spring.io/spring-cloud(现在非常流行的微服务架构)

2.Dubbo:http://dubbo.io

3.Dropwizard:http://www.dropwizard.io (关注单个微服务的开发)

4.Consul、etcd&etc.(微服务的模块)

       除了Spring Cloud,其余的微服务框架我们后续再接触学习。

常用的服务间通信方式

    因为所有的微服务都是独立的Java进程跑在独立的虚拟机上,所以服务间的通行就是IPC(inter process communication),已经有很多成熟的方案。

1.REST(JAX-RS,Spring Boot)

2.RPC(Thrift, Dubbo)

3.异步消息调用(Kafka, Notify)

       一般同步调用比较简单,一致性强,但是容易出调用问题,性能体验上也会差些,特别是调用层次多的时候。RESTful和RPC的比较也是一个很有意 思的话题。一般REST基于HTTP,更容易实现,更容易被接受,服务端实现技术也更灵活些,各个语言都能支持,同时能跨客户端,对客户端没有特殊的要 求,只要封装了HTTP的SDK就能调用,所以相对使用的广一些。RPC也有自己的优点,传输协议更高效,安全更可控,特别在一个公司内部,如果有统一个的开发规范和统一的服务框架时,他的开发效率优势更明显些。就看各自的技术积累实际条件,自己的选择了。

       异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方,同时能 保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据最终一致性;还有就是后台服务一般要 实现幂等性,因为消息发送出于性能的考虑一般会有重复(保证消息的被收到且仅收到一次对性能是很大的考验);最后就是必须引入一个独立的broker,如 果公司内部没有技术积累,对broker分布式管理也是一个很大的挑战。

微服务如何被客户端调用

       传统的开发方式,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,一般都在独立的虚拟机上的 Java进程了。客户端UI如何访问他?后台有N个服务,前台就需要记住管理N个服务,一个服务下线/更新/升级,前台就要重新部署,这明显不服务我们 拆分的理念,特别当前台是移动应用的时候,通常业务变化的节奏更快。另外,N个小服务的调用也是一个不小的网络开销。还有一般微服务在系统内部,通常是无状态的,用户登录信息和权限管理最好有一个统一的地方维护管理(OAuth)。所以,一般在后台N个服务和UI之间一般会一个代理或者叫API Gateway,他的作用包括:提供统一服务入口,让微服务对前台透明;聚合后台的服务,节省流量,提升性能提供安全,过滤,流控等API管理功能。
我的理解其实这个API Gateway可以有很多广义的实现办法,可以是一个软硬一体的盒子,也可以是一个简单的MVC框架,甚至是一个Node.js的服务端。他们最重要的作用是为前台(通常是移动应用)提供后台服务的聚合,提供一个统一的服务出口,解除他们之间的耦合,不过API Gateway也有可能成为单点故障点或者性能的瓶颈。

猜你喜欢

转载自blog.csdn.net/WYA1993/article/details/80522934