1.如何拆分微服务
从起点开始考虑:现有架构是何种形态,这个微服务是从老项目剥离出来重构呢还是新项目直接采用微服务?这个业务需求是否适合采用微服务架构。
从终点考虑:好的架构不是设计出来的,而是进化而来的,而且这个架构是一直在演进着的。
相信很多小伙伴公司的非微服务项目正处于下面这个经典架构演进图的某一个阶段,要考虑到你原本的系统处于什么阶段,原来技术栈是什么,这些都是要考虑的。虽然很多书和博客都在说从单体架构演进到微服务架构,然后说了一堆的业务拆分原则和方法,但是你公司的就是SOA系统,SOA系统和微服务之间就差了一个ESB(企业服务总线),这时候你应该考虑的是怎么做这个ESB,它和从单体架构重构到微服务要考虑的重点是不一样的。还有就是我们之前说过,分布式系统中,异构项目的存在是很普遍的,在你整个系统中,Java技术栈有多大比例,你原本的系统是不是就有服务发现、负载均衡的组件,这些是弃用呢还是整体迁移过去,都是要考虑的。
此外,还需要考虑你这个系统是不是真的适合做微服务。
2.不适合上微服务的
从业务形态上考虑:
系统中包含很多很多强事务场景的;
业务相对稳定,迭代周期长;
访问压力不大,可用性要求不高等等都是不适合上微服务的。
其他考虑:
除了从业形态上考虑,还有其他参照规律,例如康威定律
任何组织在设计一套系统(广义概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。说人话就是:沟通的问题会影响系统的设计。
例如在公司中,你总是要跟很多人沟通,经常有开会啊,影响到你的考法效率,甚至还有可能是跨时区的,这种沟通协作成本很高,就会使得你下意识的减少沟通,从而导致项目迭代进度的放缓。所以微服务提倡由小团队来负责实现,团队内部有比较细粒度的频繁沟通,这对小团队的合作是考验。
3.团队架构
传统的人员组织是以项目为组织的,从各个工种团队中抽人出来组建一个开发团队,开发完成后又释放人员回到各自团队中。
微服务的人员组织是产品模式,偏向于让一个团队负责整个项目周期,以便提供更优质的服务。这个团队要自己处理从前端到后端,从开发到运维部署的所有问题。
服务的拆分是要根据你这个系统处于哪种实际场景,面临到的问题,你的开发团队熟悉哪种技术栈,团队之间的沟通能力来决定,没有绝对的答案,都是根据实际场景来考虑。
4.点餐系统的拆分
一切不以实际场景分析的拆分都是瞎搞。比如我现在就有一个简单的外卖系统,功能比较单一,用户量一般,开发和部署上线都是我一个人,这时候你叫我搞微服务,这不是自己找事吗,就我一个开发,搞单体应用就好了嘛,微服务部署那么麻烦,增加工作量。但是如果这个外卖平台是某个公司的,用户越来越多,而且不断有新的需求,这时候就要考虑上微服务了。
如图所示有两种拆分方式,一是按手机端和PC端拆分、二是按照不同的功能模块拆分。没有绝对的拆分方案,要根据开发组里面的技术栈如何来决定采用哪种方案。比如我组里的前端人员较少,比较熟悉angular和nodeJS,这时候就考虑按手机端和PC端拆分,如果我团队里面的前端和后端人员多到我能按照每个功能模块拆分,那我可能就会选择按功能模块拆分了。
单一职责:每个服务只负责业务功能单独的一个部分。要让服务松耦合、高内聚。松耦合是指修改一个服务,另外一个服务不需要跟着修改。高内聚是指服务的相关行为都聚集在一个服务内部,而不是分散在不同的服务中,这样,修改一个行为时,只需要修改一个服务即可。如果修改一个行为会导致要修改多个服务,那么应该就是当初拆分时不够合理导致的。
关注点分离:有可能会联想到界限上下文(来自领域驱动艺术即DDD)。DDD是微服务火起来后重新复活的一个经典理论之一,它是很值得研究的,我对它只了解个基本概念而已。
按职责分离是指给我们的服务进行分类,比如一些可以按照业务领域进行划分的,服务比较单一的,比如订单、商品这类型。
按通用性分离是指一些基础组件,与具体的业务无关的也可以划分出来做一个单独的服务,比如消息服务、用户服务
按粒度级别是指微服务不是越细粒度越好,粒度是一个不大好把握的点,需要按实际情况进行划分,比如刚开始用户量很少,我把订单和支付放在同一个服务内,后面用户量激增,就需要把订单和支付拆分出来了。
拆分功能和拆分数据是有先后顺序的,应该先拆分功能,然后再拆分其对应的数据。
状态:一个数据需要被多个服务共享才能完成一个请求,那么这个数据就是状态,进而依赖这个状态的服务就是有状态的服务,反之就是无状态服务。
无状态服务并不是指微服务就不能存在这种状态,而是说要把这种有状态的服务改造成无状态的服务,如下图所示。
单独的数据存储:如果所有的微服务都共享一个共同的数据存储,他们将紧密耦合。比如更改一个微服务的表结构,会有可能导致另外一个微服务出现问题。每个微服务拥有自己的数据库后,应该避免直接访问别的微服务的数据库,不能为了图省事直接读其他库。一个服务拥有的数据只能通过API 来访问。
依据服务特点选择不同结构的数据库类型:离开业务谈技术选型都是耍流氓。要根据实际业务场景来选择采用何种数据库。比如有个服务就是用来展示数据的,类型很丰富,也不要求事务,那么就可以考虑用No-SQL的MongoDB
难点在确定边界:比如有个用户服务了,里面包含用户的基本信息、登录时间等等一大堆,然后其他服务通过API去获取想要的信息,比如订单服务要找用户服务确定一下用户是否被锁定了,而积分服务更关心的是用户登录的时间,次数等等,那么用户服务如何针对不同的业务去确定具体的 API接口,各个服务是每次通过查询接口呢还是通过某种业务机制触发查询,查询后在自己服务中保存一个副本,再通过某个服务机制同步用户数据?这个就是要权衡的点。
依据边界权衡数据冗余:比如现在订单服务是商品服务都分别是一个微服务,订单服务在生成订单时要去查询商品信息,而根据每个微服务都应该有自己的数据库的建议,从商品服务查询到的商品信息要在生成订单是产生一个商品快照,这里就要权衡数据冗余问题了。
网上很多微服务案例,只看到了微服务架构的演进结果,很多人主观或者客观的忽略了演进过程。正确的做法应该是快速的出一个微服务。微服务就是要低成本、低风险的渐进式演进服务。所以不应该一直看,一直设计,要勇于面对失败,快速开发完成后上线,看看他在实际场景会出现什么问题。
记住,微服务只是一种架构风格,具体如何落地,是根据你实际业务场景来做的,没有绝对的方案。