Microservice初体验

文章链接:http://www.cnblogs.com/loveis715/p/4644266.html

Monolith:

将所有代码和功能都包含在一个WAR包中的项目组织方式称为Monolith。

一个开发的服务,由多个项目组成,各个项目会根据自身所提供功能的不同具有一个明确的边界,编译时将这些代码打包成一个个jar包,最终合在一起形成一个WAR包,将WAR包上传到Web容器中,解压WAR包,并重启服务器。

以上这一系列操作完成之后,对服务的编译及部署就完成了。

缺点:

(1)当项目较大时,仅仅更改一行代码的情况下,需要花费几十分钟甚至更长时间对所有代码进行编译,花费大量时间重新部署刚生成的产品以验证是否正确。

(2)按照该方式组织的代码只生成一个包含所有功能的WAR包,在对服务的容量进行扩展时,只能重复地部署这些WAR包来扩展服务能力,而不是仅仅扩展出现系统瓶颈的组成。

(3)当一个服务中,某个组成的负荷达到90%,也就是必须为其服务能力进行扩容的时候,而同一服务的其他三个组成负载还没有达到其处理能力的20%。此时需要添加一个额外的服务实例讲需要扩容的组成的负载降低到45%,也使得其他各组成的利用率更为低下。


Microservice:

将整个WEB应用组织为一系列小的Web服务,这些小的Web服务可以独立的编译及部署,并通过暴露的API借口相互通讯,作为一个整体为用户提供功能,却可以独立扩容。

例如,Wikipedia包含一系列的服务,如数据访问Databases,搜索服务search等,这些服务包含数量不等的服务实例,以确保在不同负载情况下为用户提供服务,用户请求到达时这些服务协同工作,一起完成对用户请求的响应。

优点:

(1)通过编译病重新部署单个子服务的方式验证自己的更改,而不需要重新编译整个应用,节省大量时间。

(2)每个子服务是独立的,因此各个服务内部可以自行决定最合适的实现技术,使得开发更加容易

(3)如果当前系统的容量不够用了,只需要找到系统瓶颈的子服务并扩展子服务的容量即可。


关于Microservice的经验:

1、分割服务:

(1)传统编写服务活着桌面程序时首先尝试将实现的功能分割为一系列组件,并围绕组件设计完成所需要的工作流及数据流,这将导致实现业务逻辑的组件都在同一个进程之内,实现也都在一个进程之内运行。

但是,

在MicroService架构中,在尝试将需要实现的功能分割为一系列组件之前,需要将实现的功能交由彼此相互独立的一系列服务来完成。

(2)注意,

对于服务的分割和对于组件的分割是不同的,最重要的一点是在各个服务之间进行通讯的消耗相对于一个进程而言是非常大的,比进程内调用的时间长很多。

组件间的API要求具有细粒度,在当前进程中进行,速度非常快,因此频繁调用没有问题。

但是,在执行服务分割时定义的API需要粗粒度的API,以减少跨服调用的消耗。

(3)服务分割的粒度时服务分割过程中需要考虑的因素;如果一个服务的粒度太小,那么它所提供的API的粒度也不会太高。

在MicroService架构中,一个服务需要能够独立完成特定的业务逻辑,至少是某个独立资源的CRUD操作。

[CRUD:指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)、删除(Delete)几个单词的首字母简写。主要被用于描述软件系统中数据库活着持久层的基本操作功能]

(4)特殊情况:公共功能的处理。

问题:例如权限管理组件管理用户所具有的各个权限,权限管理组件实现一种公用的安全模型,如ACL(Access Control List)、RBAC(Role-based Access Control)等。在每次访问一个子服务时,这些服务都需要检查用户所具有的权限,这样会使得系统的性能变的很差。

解决方法:将各个系统中下次还能够使用的信息缓存起来,也就是在这些系统中为用户创建一个会话。

由于每个系统可能由多个服务实例所组成,为了能够重复利用会话中所储存的信息,减少向公共服务发起请求的次数,需要通过负载平衡技术让系统中的同一个服务实例处理同一个用户的请求。如何实现该功能?http://www.cnblogs.com/loveis715/p/4547968.html

问题:公共服务会与各个服务产生一种逻辑上的依赖关系。

当权限管理的组成存在于多个服务之中的时候,可以直接通过传入用户的信息以及需要访问的资源判断出用户是否能访问特定资源,也就是说,从权限管理的组成所返回的实际上是一个布尔类型的数据。

但是管理权限时一个服务时,为避免每次都调用权限管理服务,需要在用户的会话中记录用户所具有的权限。在用户下次访问该服务时,可以直接检查该用户所具有的所有权限就能决定是否可以访问特定资源。

在用户会话中记录的的权限常常具有某种特定的表现形式,如特定形式的字符串,而这种字符串需要同时被服务和权限管理服务所理解,从而造成两个服务之间的耦合。

增大的耦合性会导致服务的重用性下降。

因此在分割过程中,服务的总体性能是至关重要的,而各个服务之间的独立性也是关注的特性。


2、共享服务:

(1)在MicroService架构模型中,常需要一系列公有服务来辅助整个系统的运行。这些服务包括:权限管理服务,能够监控各个服务实例的服务状态,服务实例的添加删除升级管理等等。

在刚开始使用Microsercive架构模式应用开发的时候,效率明显低于通过Monolith进行开发的效率;但是随着应用规模的增大,Microservice的开发效率明显上升,而基于Monolith模式的效率逐步下降。

(2)Microservice在开发初期效率低下的原因:

公共服务需要在编写第一个子服务的同时进行,这也是导致Microservice架构模式在开发初期效率低下的一个原因。

公共服务在保持和各个子服务的松耦合性的同时还需要提供一个足够通用的、在一定程度上满足当前和未来子服务要求的解决方案,这是另一个原因。

3、模型匹配:

在Microservice架构模型中,各个服务是彼此独立的,而且是关注于自身业务逻辑的,因此在看待一个事物时,可能会有不同的视角,进而造成各个子服务中的对应模型并不匹配。

问题:当子服务的模型较少时,服务之间的依赖关系并没有很多,那么这种模型匹配还能够解决,但是如果各个子服务之间的沟通很多,那么各个子系统之间的模式匹配就会很复杂。

解决方法:使用公共服务对他们进行管理。在提供一个集中的公共服务的情况下,就不再需要处理这么多的模型转换了。

注意:对角色进行匹配并不合适,因为对于不同的角色对同一个资源有着不同的操作权限。

在集中的公共服务中,需要使用较为细粒度的模型,该模型具有较高的灵活性,以能够无损的表示各个服务中的相应模型。

问题:Microservice架构模型简化了单个子服务的实现,但是复杂了数据的处理,常见的麻烦有:保持多个子服务之间数据的一致性,粒度等。

解决方案:保持一致性的的工作通常是由事务来完成的,那么Microservice中保持子服务之间数据一致性可以通过分布式事务来实现。但是实现分布式事务并不简单,因此需要反思需要事务来保持数据一致性的子服务是否应该属于同一个服务。另外关于粒度的问题,各个子服务之间所提供的API应该尽量的粗,但应尽量保持灵活性,最好的情况时通过一个服务间调用就获得所有想要的信息。



Microservice实现:

1、问题:子服务之间哪里可以出现耦合?出现什么程度的耦合?

Ans:UI。运行在用户浏览器中的UI需要与其他各个子服务进行交互,因此UI可以作为中介者来完成各个子服务之间的交互。

因此在基于Microservice架构模式的服务中,常会出现一个前端服务。该服务所提供的页面会与各个服务沟通,但它实际上不需要与其他服务之间进行通讯。

2、Ques:像上面这种情况,各个子服务就没有UI了,而UI服务不仅仅处理所有的前端业务逻辑,而且如果需要介入第三方服务接入,打包在一起的UI服务将变成整个平台的阻碍。

Ans:(1)在应用中尝试借鉴Service Locator模式。此时需要的是一个UI框架,允许用户通过特定方式在应用中插入各个子服务所提供的UI,并允许,并允许通过一些机制来发现已经在平台中注册的具有特定功能的API,并允许对该API进行调用。

 (2)另一种模式是Message Broker,简单的说就是一个消息的中转平台,允许其他组成向其中注册消息,也允许其他组成组成侦听消息。当一个组成将一个消息发送到了Message Broker之上后,其他侦听该消息的各个组成则会根据消息中包含的信息更新自己的状态。

3、Ques:如果服务需要支持移动设备,就不能让这些移动设备一个一个访问子服务了。因为这些移动设备的带宽一般都非常小,且用户常处于信号不太好的地方,因此向这些子服务一个一个地发送请求将快速消耗掉他们所拥有的有限的带宽。

Ans:通常在这些子服务之前搭建一个代理服务,代理服务将用户请求根据业务逻辑拆分为对各个子服务的请求,并将各个子服务所返回的结果归纳为一个相应返回给用户。

4、如何创建各个子服务所需要的公共服务?

对公共服务的调用是一个跨进度调用,因此相较于进程内调用效率低下,这种情况下需要尽量避免对该公共服务的重复调用,因此需要尽量使用户访问同一个子服务实例,并在该用户的会话中缓存从公共服务中所得到的信息。

因此在同一个子服务的各个服务实例上,需要尽量使用负载平衡的Sticky Session的功能,并在一次公共服务调用中取得多项信息。
例如在查看用户的权限时,不是查看用户是否具有特定权限,而是用户拥有哪些权限。

公共服务API的粒度需要粗一些,且同时具有一定的灵活性,从而通过减少服务间调用来避免整个服务的性能瓶颈。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章