不知从何时起,与同事,面试者,面试官谈起架构理念,总是绕不开微服务。甚至有时候听到这三个字的时候,脑壳会痛,相似的还有中台, 总觉得是旧瓶装新酒。 当然此时的盛行是有其原因的,猜测主要原因是容器化的盛行。
架构和微服务的定义:
能给出合适的定义才能表明一个人真正理解了所描述的事物。
架构:
按照一定的方法设计出来,把系统划分成颗粒合适,边界分明,复用合理的模块。这里的关键词是颗粒合适,边界分明, 合理复用。
微服务:
颗粒度较小的架构,关注点是颗粒度相对较小。
为什么要存在架构和微服务架构:
大部分事物存在的理由都是带来了价值或者解决了问题,架构或者架构师存在的意义也是解决问题。合理架构带来的直接帮助是节省了因为改动引起的工时变化。 (改动 这个关键字圈出来。) 当然还有一部分是带来性能的提升或者是安全性。
假设架构师或者业务的owner对业务没有太多的前瞻,那么业务初始的必然是一个大应用。随着时间的推移会慢慢发现大应用的问题:
-
一个团队难以维护这么的系统,理解和沟通麻烦,出现边界不清大量扯皮。
很多人都会说用写文档解决问题,一方面高强度的开发,和利他主义薄弱的个体难以主动维护文档。另一方面读文档也存在理解偏差的情况。所以一个系统要让别人理解,最好设计本原就是好理解的。
2. 系统之间互相影响,工程效率/测试效率,安全性也受到影响。
一个核心系统与非核心系统,无论是发布还是出现问题的报警处理级别都是不一样的。因为一个后台管理系统发布或者出bug导致支付业务挂了, 就会让外界感觉匪夷所思。因为要保证核心功能不受一些非核心的影响,每次发布重新覆盖所有流程。
所以我们出现微服务就是为了解决上述问题。
如何指导架构:
至此为止,我们可以把微服务架构当成一种边界清晰,颗粒合理的架构方式,以下的架构方法论主要会围绕微服务来讲。
架构的方法论非常之多,然后我们做任何事情都要找到第一性原理。在软件生命周期中,如果它一直是一尘不变的,那么他设计成啥样都无所谓,因为测试完成交付就可以了。但是如果有变化,意味着我们会因为改动而产生bug, 因为改动而发现代码无法维护。
所以我们设计类,应用,系统架构遵循的核心考量标准就是 在有变化的前提下,能否更轻易的应对变化。
在有变化的前提下:
一个模块或者系统如果不可能发生变化,或者频率极低,就需要考虑是否需要为应对变化而付出成本,因为要应对变化必然要有一些开闭或增加理解成本和编码成本。 就类似spring的code就非常复杂,作为一个开源工具,必然需要更多的extension。但是如果一串几乎不改的业务代码有非常多的设计模式,看起来层层叠叠,那你肯定想杀了他。
再多说几句,其实设计模式这本书本身不是指导程序员开发的,而是一本通识类的书,告诉你某种写法叫啥。当某段程序需要变化的时候,必然会去想怎样能更好应对变化,而不是想起自己有个锤子,看地球都是钉子。
能否轻易应对变化:
这时候我们可以一生而二了。轻易应对变化就是修改一个模块时,需要做到高内聚,低耦合。它的变化封闭在本模块中这就是所谓的高内聚。如果你修改了一个模块对其他模块的影响很小那就是所谓的低耦合。
更具体的措施:
从更宏观的多个微服务来看,我们需要做到 边界清晰,颗粒合适,复用合理。
边界清晰:
为啥要边界清晰:
边界清晰的首要好处是低耦合。如果你的应用架构图设计看来是一个网,那大概率是不太合理,因为这样应对变化不太灵活。主要的可能是本该在一起的功能被拆开到了其他系统中。
怎样做到边界清晰:
用领域建模去建立业务模型, 如果是DownTop根据业务用例,分析动名词去提取构建业务模型。 例如男孩小明今年9岁,他去超市买了瓶水这个用例我们可以分析出 领域小孩: [性别,年龄]。 超市:[商品]。
TopDown是为了解决现有问题,主要还是宏观的问题论,不再这里讨论。
颗粒合适:
为啥要颗粒合适:
-
过分的拆分微服务影响性能,从进程内通信变成了RPC通信。
-
如果团队人数过少,维护成本特别高。最极端的情况一个人兼任owner,加另一个系统的备。
-
系统过多,监控运维成本也很大。
怎样做到颗粒合适:
根据团队去划分,让团队内的沟通更专注。系统的数目绝对不要超过团队的人数。
合理复用:
为啥要合理复用:
首先微服务强调的是隔离,因为很好的隔离性才能让这么多的服务稳定的跑下去。但是一个系统不可能没有重复模块。那我们反证一下不合理的复用有什么缺点:
完全不复用: 系统有很多冗余代码,会出现散弹式的修改,更有可能是忘记修改。
不灵活的复用: 打成jar或者dll,被多个系统依赖。每次改动jar的逻辑,为了同步改动发布多个依赖应用。
独立应用隔离: 运维维护成本超级高。
怎样合理复用:
多份冗余代码: 对于几乎不变,依赖方少于3个的或逻辑可能出现分裂的模块。
打成jar或者ddl: 对于功能几乎不变,且依赖方相对较多的功能模块如工具类。
下沉成应用:功能逻辑被多处引用,且逻辑变化频繁。
越是依赖多的,越是改动多的,复用方式就要越灵活。
下一篇我们会讲如何应用领域建模的方式来应对实际场景