凡架构必拆分,分则有度
《三国演义》开篇卷首语就说:“天下大势,分久必合,合久必分。”古往今来,人类的历史都在是分分合合的过程中不断的发展的。中国自古幅员辽阔,民族众多,就像一个超大型的系统,面对这样复杂的系统的管理,在治理架构上就存在巨大的挑战。自古古人就普遍使用分治思维来进行国家治理,从秦朝之前的分封制,到自秦朝开始的郡县制,再到现在的共和制、联邦制都是分治思维的体现。
分而治之是解决管理系统复杂度的普遍方法,合并、拆分、协同、自治是所有架构都会包含的主要元素。
从分治算法谈分治思维
对于程序员来说,分治法是一种很重要的算法,也是分治思维最基本的体现。分治算法主要的三个过程:
1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----“分”
2.将最后子问题可以简单的直接求解----“治”
3.将所有子问题的解合并起来就是原问题打得解----“合”
举例:找出一组单词共同的前缀,应该如何做?
第一步:将这一组单词两两分组(分);通过贪心算法查找两个单词的共同前缀(治);重复以上过程,将结果再两两分组查找,最终找到所有单词的前缀(合)。
通过分治算法我们可以统一抽象出分治思维的逻辑过程,如下图所示:
分治的好处是:问题越小越容易被解决,并且,只要解决了所有子问题,父问题就都可以被解决了。
MapReduce分布式计算框架
web应用的负载均衡
数据库的水平分库,水平分表
以上的几种常见的实际的分布式架构应用都恰恰的完全匹配了上图中分治的思想。但是,这种分治方式,需要满足一个最重要的条件:不同分支上的子问题,不能相互依赖,需要各自独立。因为一旦包含了依赖关系,各部分之间就存在了耦合度,整个体系的复杂度就提升了。在分布式系统中,往往根据业务垂直切分的分治方式,就不可避免的存在依赖和耦合。
比如一个电商平台,为了应对更大的访问量,需要拆分一个同时包含商品、促销的系统,拆分后如下图所示,各分治单元之间依然存在耦合关系。
但是耦合关系要比之前没拆分之前降低了,之前耦合关系是6,现在减少为4,且商品和促销各自的处理相互不受影响。
所以,你会发现随着业务的变化,耦合度与内聚度也会发生变化。因此,及时地进行梳理和调整,可以避免系统的复杂度快速增长,才能最大程度的发挥“分治”带来的好处。
如果说水平拆分更多的是解决计算的弹性,而垂直拆分则更多解决解决业务的复杂度的问题,在我们实际的应用中,水平拆分和垂直拆分经常同时存在,分治后虽然解决了弹性和业务复杂性的问题,但也伴随着合并集成、运维管理的复杂度的升高。随着微服务架构体系的成熟,像SpringCloud这样的微服务治理的集成框架很大程度上缓解了这方面的问题。
单体架构 VS 微服务架构
当下这个无微服务不架构的时代,我们身在其中,已然没有选择。但是向前五到十年,单体应用架构的天下,即使分布式架构已经被广泛实施,其实更多的还是以单体应用的水平扩展为主。现如今的大行其道的微服务架构也是逐步的从单体架构向分布式架构一步步的演化而来,而分治思维则是其核心指导思想。
单体架构
就是一个产品(或项目)一个交付物,如果是Java开发的话,通常是一个带有单一入口的WAR/JAR包,所有的业务逻辑全部包含在这个文件里,或许是通过模块化开发后集成,分层设计,最终从上到下形成一个不可分割的整体。
单体架构开发模式简单,部署发布也非常简单,这是单体架构比较明显的优势。但是单体应用所有的代码一般都在一个工程里(可以通过微内核+插件的方式进行代码层面的分治管理),随着业务的扩展,时间的推移,代码就会难以管理,后期维护的成本很高。同时,单体应用的弹性扩展的能力较差,而且可用性随着并发的提高也会变差,无法更细粒度的进行弹性扩展。
微服务架构
>微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
优点
低耦合
更容易做到高内聚低耦合,因为服务是独立的,从一开始就完全解耦,边界清晰,所以更容易保持各自的模块化实现;
复用
大部分采用微服务架构的公司,一个微服务有一个独立的团队来长期维护,对外提供标准的不同版本的接口,只要其他产品有此类需求,就可以对接,一个微服务,可以在多个产品中复用;
高效
由于服务本身所承担的业务功能的单一,决定它的规模和体积都不会太大,并且有独立的维护团队,使得沟通、项目编译启动的速度、测试、部署CICD 都变得会非常高效;
异构性
每一个微服务可以有自己的技术选型,技术实现相互隔离,可以选择更好的满足自身特点的技术,并且老的服务可以更容易的完成自我重构和技术迭代升级;
故障隔离
相对单体架构,这一点更容易做到,故障的影响范围可以缩小到故障服务自身,通常使用熔断、降级等手段,提升整个系统的稳定性
缺点
运维要求高
更多的服务意味着要投入更多的运维。
分布式固有的复杂性
使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延迟、分布式事务等都会带来巨大的问题。
接口调整成本高
微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有用到这个接口的微服务都需要进行调整。
微服务设计原则
私信回复:“微服务”,分享给你一个ThoughtWorks编写的微服务架构PPT。
拆分有度
拆分的原则
任何技术和理念都将不能成为解决一切问题的银弹,有的只是权衡和选择!微服务架构作为当前最流行的架构模式被广泛应用,但是使用不当或者拆分不合理也会导致增加额外的负担,得不偿失。所以在运用分治思维进行架构拆分时,需要遵守一些常用的原则:
单一职责,高内聚、低耦合
服务粒度适中,粒度太粗难复用,粒度太细成本高
考虑团队结构,遵守康威定律
以业务模型切入,使用领域驱动设计(DDD)
演进式拆分
避免环形依赖与双向依赖
拆分的工具
领域驱动设计(DDD)
领域驱动设计是一种处理高度复杂域的设计方法,试图分离技术实现的复杂性,围绕业务概念构建领域模型来控制业务的复杂性,以解决软件难以理解,难以演化等问题。
领域驱动设计最核心也是最难掌握的就是领域边界的划分,这也是分治思维的核心。
参考我的DDD的学习笔记:https://processon.com/view/5eccb5381e08530a9b1f3b48
康威定律
五十多年前,在康威的这篇文章中,最有名的一句话就是:
Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.
中文直译大概的意思就是:设计系统的组织,其产生的设计等同于组织之内、组织之间的沟通结构。更直白的说,你想要什么样的系统,就搭建什么样的团队。
如果你的团队分成前端团队,Java后台开发团队,DBA团队,运维团队,你的系统就会长成下面的样子:
相反,如果你的系统是按照业务边界划分的,大家按照一个业务目标去把自己的模块做出小系统,小产品的话,你的大系统就会长成下面的样子,即微服务的架构
拆分是架构设计的手段而非结果,所有的系统都是物理上拆分,逻辑上整合;底层拆分,上层聚合。拆分是一个过程,分分合合就是度的把握,没有一步到位的设计,只有演进式调整。所以下一章节我给大家分享架构思维另一个重要思维:演化思维。
《程序员的思维修炼》是菜根老谭结合自己的工作经历和对这个岗位发展的认知而专门开辟的一个专栏,旨在分析程序员的职业发展的过程中我们应该锻炼哪些思维意识,如何去合理正确的看待事物,如何形成适合自己发展的思维体系。本专栏既是对过去思考的总结,也是对自己发展所具备的能力的思考,希望这些内容能陪我成长,帮大家解疑答惑。该专栏首发今日头条,关注我的同名头条号和微信公众号获取更及时的内容推荐。
版权声明: 本文为 InfoQ 作者【菜根老谭】的原创文章。
原文链接:【http://xie.infoq.cn/article/b849d2e2a753ee138c3cd9450】。文章转载请联系作者。
评论