架构师训练营 -week10- 总结
本周重点学习了以下几个方面的内容:
微服务的演进过程
微服务落地实践经验
微服务网关技术剖析
DDD 和组件设计原则
架构演进过程:单体架构 -> SOA 时代 -> 微服务时代
单体架构和微服务的分布式架构的优缺点比较:
分布式系统架构的难点在于系统设计,以及管理和运维。所以,分布式架构解决了“单点”和“性能容量”的问题,但却新增了一堆问题。而对于这些新增的问题,还会衍生出更多的子问题,这就需要我们不断地用各式各样的技术和手段来解决这些问题。这就出现了我前面所说的那些架构方式,以及各种相关的管理型的技术方法。这个世界就是这样变得复杂起来的。
提高系统性能的常用技术手段:
提高系统稳定性的常用手段:
微服务具备的 9 大特征:
第一,围绕业务能力构建(Organized around Business Capabilities)
这个核心技术特征,实际上再次强调了康威定律的重要性。它的意思是,有怎样的结构、规模和能力的团队,就会产生出对应结构、规模、能力的产品。这个结论不是某个团队、某个公司遇到的巧合,而是必然的演化结果。
第二,分散治理(Decentralized Governance)
这个技术特征,表达的是“谁家孩子谁来管”。微服务对应的开发团队,有着直接对服务运行质量负责的责任,也应该有着不受外界干预,掌控服务各个方面的权力,可以选择与其他服务异构的技术来实现自己的服务。
微服务更加强调的是,在确实有必要进行技术异构的时候,一个开发团队应该能有选择“不统一”的权利。比如说,我们不应该强迫用 Node.js 去开发报表页面;要做人工智能计算的时候,也可以选择用 Python,等等。
第三,通过服务来实现独立自治的组件(Componentization via Services)
第四,产品化思维(Products not Projects)
产品化思维的意思就是,我们要避免把软件研发看作是要去完成某种功能,而要把它当做是一种持续改进、提升的过程。比如,我们不应该把运维看作就是运维团队的事,把开发看作就是开发团队的事。
以前在单体的架构模式下,程序的规模决定了我们无法让全部的开发人员,都关注到一个完整的产品,在组织中会有开发、运维、支持等细致分工的成员,他们只关注于自己的一块工作。但在微服务下,我们可以让团队中的每一位成员,都具有产品化思维。因为在“2 Pizza Tems”的团队规模下,每一个人都了解全过程是完全有可能实现的。
第五,数据去中心化(Decentralized Data Management)
微服务这种架构模式也明确地提倡,数据应该按领域来分散管理、更新、维护和存储。
在单体服务中,通常一个系统的各个功能模块会使用同一个数据库,虽然这种中心化的存储确实天生就更容易避免一致性的问题,但是,同一个数据实体在不同服务的视角里,它的抽象形态往往也是不同的。
尽管在分布式中,我们要想处理好一致性的问题也很困难,很多时候都没法使用传统的事务处理来保证不出现一致性问题。但是两害相权取其轻,一致性问题这些必要的代价是值得付出的。
第六,轻量级通讯机制(Smart Endpoints and Dumb Pipes)
ESB 可以处理消息的编码加工、业务规则转换等;BPM 可以集中编排企业的业务服务;SOAP 有几十个 WS-* 协议族在处理事务、一致性、认证授权等一系列工作。这些构筑在通讯管道上的功能,也许在某个系统中的确有一部分服务是需要的,但对于另外更多的服务来说是强加进来的负担。
如果服务需要上面的某一种功能或能力,那就应该在服务自己的 Endpoint(端点)上解决,而不是在通讯管道上一揽子处理。
微服务提倡的是类似于经典 Unix 过滤器那样,简单直接的通讯方式。比如说,RESTful 风格的通讯,在微服务中就是比较适合的。
第七,容错性设计(Design for Failure)
容错性设计,是指软件架构不再虚幻地追求服务永远稳定,而是接受服务总会出错的现实。
可靠系统完全可以由会出错的服务来组成,这是微服务最大的价值所在。
第八,演进式设计(Evolutionary Design)
容错性设计承认服务会出错,而演进式设计则是承认服务会被报废淘汰。
一个良好设计的服务,应该是能够报废的,而不是期望得到长久的发展。如果一个系统中出现不可更改、无可替代的服务,这并不能说明这个服务有多么重要,反而是系统设计上脆弱的表现。微服务带来的独立、自治,也是在反对这种脆弱性。
第九,基础设施自动化(Infrastructure Automation)
基础设施自动化,如 CI/CD 的长足发展,大大降低了构建、发布、运维工作的复杂性。
由于微服务架构下,运维的服务数量比起单体架构来说,要有数量级的增长,所以使用微服务的团队,会更加依赖于基础设施的自动化。毕竟,人工是无法运维成百上千,乃至成千上万级别的服务的。
以上 9 个特征,是一个合理的微服务系统展示出来的内、外在表现,它能够指导你该如何应用微服务架构,却不必作为一种强加于系统中的束缚来看待。
落地实践中的知识点,把这周涉及到的列出来:
Dubbo 框架
CQRS:命令与查询职责隔离,读写分离
事件溯源:将用户请求处理过程中的每次状态变化都记录到事件日志中,并按时间序列进行持久化存储
微服务网关:统一接入、安全防护、流量管控与容错、协议适配
开放授权协议 Oauth2.0
领域驱动设计(Domain Driven Design,简称 DDD):
DDD 是一种处理高度复杂领域的设计思想,它试图分离技术实现的复杂性,并围绕业务概念构建领域模型来控制业务的复杂性,以解决软件难以理解,难以演进的问题。DDD 不是架构,而是一种架构设计方法论,它通过边界划分将复杂业务领域简单化,帮我们设计出清晰的领域和应用边界,可以很容易地实现架构演进。
DDD 包括战略设计和战术设计两部分。
战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界。
战术设计则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。
领域:领域是一个组织所做的事情以及其包含的一切,通俗的说,就是组织的业务范围和做事方式,也是软件开发的目标范围。
DDD 主要关注:从业务领域视角划分领域边界,构建通用语言进行高效沟通,通过业务抽象,建立领域模型,维持业务和代码的逻辑一致性。
微服务主要关注:运行时的进程间通信、容错和故障隔离,实现去中心化数据管理和去中心化服务治理,关注微服务的独立开发、测试、构建和部署。
贫血模型 VS 充血模型:
基于贫血模型的传统的开发模式,比较适合业务比较简单的系统开发。
相对应的,基于充血模型的 DDD 开发模式,更适合业务复杂的系统开发。比如,包含各种利息计算模型、还款模型等复杂业务的金融系统。
我们平时做 Web 项目的业务开发,大部分都是基于贫血模型的 MVC 三层架构,在专栏中我把它称为传统的开发模式。之所以称之为“传统”,是相对于新兴的基于充血模型的 DDD 开发模式来说的。基于贫血模型的传统开发模式,是典型的面向过程的编程风格。相反,基于充血模型的 DDD 开发模式,是典型的面向对象的编程风格。不过,DDD 也并非银弹。对于业务不复杂的系统开发来说,基于贫血模型的传统开发模式简单够用,基于充血模型的 DDD 开发模式有点大材小用,无法发挥作用。相反,对于业务复杂的系统开发来说,基于充血模型的 DDD 开发模式,因为前期需要在设计上投入更多时间和精力,来提高代码的复用性和可维护性,所以相比基于贫血模型的开发模式,更加有优势。
子域:通常一个领域拆分成多个子域
限界上下文:在一个子域中,会创建一个概念上的领域边界,在这个边界中,任何领域对象都只表示特定于该边界内部的确切含义,这样的边界便称为限界上下文
上下文映射图:不同的限界上下文,也就是不同的子系统或者模块之间会有各种的交互合作。DDD 使用上下文映射图来设计这种交互。
实体:领域模型对象。每个实体都是唯一的,具有一个唯一标识
值对象:值对象是不变的,没有行为和状态,仅仅用来作为度量或描述的对象。
聚合:关联对象的集合
聚合根:将多个实体和值对象聚合在一起的实体
评论