“⼀学就会,⼀做就废”——微服务的架构模式:⼀个服务⼀个
数据库模式(中)
今天这篇⽂章我想谈谈:
⼀个服务⼀个数据库这种最基本的模式落地,⼤体的做法是怎么样的。
⼀、搞微服务,可能是个政治问题
我第⼀次接触微服务的时候,真的是迫不得已。
公司有⼀套⼤型系统,这套⼤型系统当时是负责公司的主要盈利业务,⾮常⾮常重要。但是,正因为重要,所以它就成为了产品、业务团队的重点服务对象。这些⼈天天想着把这套系统的业务做出花来,不断对技术团队提出各种各样的需求。
提出需求不说,还要求技术能快速迭代。⼀旦不能及时上线他们的需求,产品经理们就会在各种会议上抱怨,说技术团队影响了速度,出现了让竞争对⼿迎头赶上的风险。
技术团队有⼝难⾔,因为系统太庞⼤了,改动那么⼤的系统真的很困难。⾄于原因,我也在上篇⽂章说了,不再赘述。
出于这些原因,我们决定采⽤微服务。
什么时候使⽤微服务?当你的交付时间不够应付产品团队,不够应付运营团队的时候,考虑考虑。还有,我后来搞其他新项⽬时,领导认为系统太简单,没有⾃⼰的技术特⾊。不得已,我⼜拿出了微服务,领导看了之后,眼前⼀亮,直说这个好。
所以,以我的经验看,有时候搞微服务,本质是个政治问题不是技术问题。
总的来说,对于微服务落地,不是特别⼤型的项⽬,微服务带来的好处不⼤,⼯作量反⽽增⼤了许多。
不管什么原因,我后续接触的微服务越来越多了,为了⽤好微服务,我真的是狠狠钻研了下微服务这套体系架构,也总结了⼀些⾃⼰对微服务分解实践的经验。
⾸先,如果是预估到业务在飞速增长,那就别犹豫,⼀定要提前考虑微服务的拆分。
其次,如果在设计架构的时候,发现需要很多异构的技术栈,那也要考虑下微服务。
最后,如果公司技术基础设施⾮常完备,对应的业务起初就设计的⾮常复杂,那么也别犹豫,起⼿就上微服务。
⼆、迁移到微服务可以很粗暴,也可以很温柔
回过头来,继续说我当时第⼀次搞微服务的事情。
由于迁移微服务不是⼀蹴⽽就的事情,但是我⼜急需⼀些微服务的部署简单、开发快速的优点。所以,当时不得已,想了个折中的办法。
我把⼀些急需实现的业务需求分析了下,发现这些需求⼤体可以分为以下两类:
1. 有些需求本⾝是⼀套独⽴的边缘业务
2. 有些需求是集中在核⼼业务的边缘上
我后来想想,觉得这是理所应当的。业务和我们技术⼀样,如果动了核⼼业务的逻辑,万⼀出现了问题,他们是要背⼤责任的。但是他们⼜要体现⾃⼰的价值,那最保险的就是在核⼼业务的边边⾓⾓动些⼿脚。
知道了这些,那就好办了。
对于第⼀类独⽴的业务需求,我直接就设计出⼀套独⽴服务,让它和已有的⽼系统通过⽹络远程互联。这样的话,新搭建的服务很⼩,维护也简单。以前的⽼系统也成为新服务的服务。这样,⼀部分需求,就可以快速迭代了。
对于第⼆类需求,原有系统核⼼边缘的需求,我是这样做的。
⾸先,我争取了领导的⽀持,优先对经常被提需求的业务模块做了剥离。这样,就剩下了⼀些不经常变动的业务模块还在⽼系统。其实这些时候,系统也没那么⼤了,也能满⾜业务偶然提出的业务变动需求了。
然后,我会在后续的时间⾥,慢慢的抽空把剩下的业务模块没事⼉就剥离⼀些出来。但是,优先级很低。
这样,慢慢的抽丝剥茧,最后,我发现,核⼼业务我们都没有动,⼀套微服务体系就已经搭建出来了。
有⼈可能会⽐较好奇,你这样剥离,同时存在⽼系统和新系统。那外⾯的⽤户使⽤会不会受影响呢?
其实,这⾥还有个⼩技巧。就是我在拆微服务之前,先搭建了⼀个代理。这个代理就是专门路由外⾯⽤户请求的。每次上线服务的时候,都会对这套代理进⾏⼀次微调整。这样搞下来,⽤户是感知不到背后新⽼系统并存的状态的。
但是,说到这⾥,我也要说⼀下,这个⽅法真的是⽐较粗暴的,是实在没办法才选择这种⽅法。
后来,我再搞微服务的时候,吸取了很多教训。总的⽅向还是需要优先划分出清晰的业务模块,然后再根据业务模块的划分搞出微服务来。
总的来说,后期我设计微服务架构需要分为两个时期。⽽在这两个时期,我⼜采⽤了不同的办法。我分别来说说。
三、⼟法炼钢的传统业务划分
在第⼀次被迫搞了微服务后,我对微服务这个架构开始了⾃⼰的研究。我知道了很多技术⽅⾯的细节,⽽如何划分业务,我承认当时⾃⼰有点疏忽。所以,后来再有了新项⽬,我搞微服务的时候,是⽤的传统业务划分⽅法搞的微服务。
步骤如下:
第⼀步:划分功能模块
功能模块划分清楚这事⼉其实还好,如果是从零开始的系统,业务尚不复杂,所以模块也很容易划分清楚。
如果是已有的⼤项⽬,那还得看看系统的源码,根据源码和业务⽂档,把整体业务模块搞清楚。
第⼆步:梳理功能模块的⽅法
搞清楚业务模块了还不够,你还需要搞成分开的服务,所以,必定需要把服务之间的联系也给确定好。这时候,如果是从零开始就很好搞了,⾃⼰根据业务划分的情况,直接⾃⾏创建对应的⽅法就好。
如果针对已有项⽬拆分,那就不好搞了。⾮得仔细梳理源码,然后根据源码的类和⽅法,逐次清理出各个模块的之间的⽅法调⽤。⾮常⿇烦。
第三步:对⽅法进⾏分类
把梳理出来的所有⽅法做⼀次分类,分成两类:功能模块直接对外部⽤户的⽅法,功能模块内部之间需要调⽤的⽅法。
第四步:模块映射服务,⽅法映射 API
⽅法梳理好了,分类完毕了,这时候得把功能模块映射成服务了,这个过程是必不可少的。功能模块映射成服务往往⼀开始其实很粗糙,就是先把⼀个功能模块和服务进⾏⼀对⼀的映射。
但是,就我的经验来说,这么简单的映射⼏乎是不可能的。总是有各种落地问题迫使你再调整。
好了,做出了业务模块和服务的⼀对⼀映射的假设,咱们也梳理了业务模块的⽅法调⽤了。那就把这些⽅法调⽤和服务的 API ⽅法做个⼀对⼀映射。当然,这个⽅法也是很粗糙的,⼏乎总是存在需要调整的问题。
第五步:根据实际情况做调整。
最后,就开始根据咱们上⾯的假设开始微调了,业务模块和服务之间的映射被迫调整,主要因为以下⼏个原因:
1. 拆分后过多的⽹络交互引起性能下降
当我们拆分服务后,以前有些业务模块间频繁的⽅法调⽤,映射到服务之间,就变成了频繁的⽹络交互了。
我们肯定不能任其这样频繁的⽹络调⽤。对这种情况,就会有两个办法处理:1. 把服务之间的交互改成批量处理的⽅式;2. ⼲脆就不拆服务。
服务之间改成批量处理还好,⼀旦决定不拆,就影响了以前设计好的映射关系了。
常用微服务架构2. 同步调⽤可能引起的阻塞
还有些时候,以前本地调⽤搞成同步的⽅式,其实⽆伤⼤雅。因为⼤家在同⼀个进程⾥,处理事件都可以忽略不计。
但是,如今分家了,搞成了服务之间的⽹络调⽤,那事⼉可就来了。⽹络同步调⽤必须考虑容错和阻塞,所以,对于同步调⽤这种,也得从两个⽅⾯处理:1. 设置超时;2. 搞成异步⽅式处理。
如果⼀些同步⽅法搞成了异步⽅式,那服务的 API 和以前的⽅法映射关系可能就要调整了。
例如⼀个⽅法得对应两个异步 API:⼀个是访问,⼀个是获取响应。
3. 原来的数据⼀致性可能要重新考虑
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论