第十周总结
1. 微服务
1.1 单体应用
产品早期,业务逻辑相对简单,用户量也不大,为了快速试错验证市场,一般采样单体架构,也就是打成all in one 的包。其优点是学习成本低,开发上手快,测试、部署、运维也比较方便,甚至一个人就可以完成一个网站的开发与部署。但是随着业务规模的不断扩大,团队开发人员的不断扩张,单体应用开始面对几方面的问题:
编译、部署困难
代码分支管理困难
数据库连接耗尽
新增业务困难
解决问题的方案就是拆分,将模块独立部署,降低系统的耦合性
纵向拆分:将一个大应用拆分为多个小应用,如果新增业务较为独立,那么久直接将其设计部署为一个独立的web应用系统。
横向拆分:将复用的业务拆分出来,独立部署为微服务,新增业务只需要调用这些微服务即可快速搭建一个应用系统。
1.2 微服务框架
早期RPC框架web service
web service 是 JavaEE规范之一,也是比较早期的RPC框架。

服务提供者通过WSDL向注册中心描述自身的服务接口属性,注册中心使用UDDI发布服务提供者提供的服务,服务请求者从注册中心检索到服务信息后,通过SOAP和服务提供者通信,使用相关服务。
主要缺点:
(1) 臃肿的注册与发现机制
(2) 低效的XML序列化手段
(3) 开销相对较高的HTTP远程通信
(4) 复杂的部署与维护手段
这些问题导致web service 难以满足大型网站对系统高性能、高可用、易部署、易维护的要求。
微服务框架的需求
(1) 失效转移 (Fail Over)
(2) 负载均衡
(3) 高效的远程通信
(4) 对应用最少侵入
(5) 版本管理
微服务框架dubbo
dubbo是通过嵌入代码的服务框架(SDK)的方式,进行服务治理的。

下一代微服务service mesh
service mesh 是通过side car,进行服务治理的,应用程序可以把更加专注业务逻辑,而不用关心具体的服务治理。


1.3 微服务架构实践
业务先行,先理顺业务边界和依赖,技术是手段而不是目的
先有独立的模块,后有分布式的服务
业务耦合严重,逻辑复杂多变的系统进行微服务重构要谨慎
要搞清楚实施微服务的目的是什么,业务复用?开发边界清晰?分布式集群提升性能?
CQRS命令与查询职责隔离:服务接口层面读写分离
断路器:解决服务短时间故障与恢复,三种状态:关闭,打开,半开
服务重试及调用超时
最重要是需求:

1.4 微服务网关
API 网关是外部系统访问的接口,所有的外部系统接⼊系统都需要通过 API 网关,主要包括统一接入、安全防护、流量管控与容错、协议适配等功能。


外部请求在经过API网关的时候,网关会进行一系列的校验、拦截等操作,可以通过责任链模式设计:

如果网关是开放平台的网关,可以通过oauth2实现授权(认证需要自己实现)



oauth2.0的四种模式:

2. 领域驱动设计DDD
2.1 什么是DDD
DDD 是一种在面向高度复杂的软件系统时,关于如何去建模的方法论,它的关键点是根据系统的复杂程度建立合适的模型。DDD为领域模型提供了一些方法支持和最佳实践,来最终实现领域模型。
2.2 为什么需要DDD
产品初期,软件只做了需求分析,技术层面的架构设计,但是并没有做系统的设计(组件模块划分,模块的边界,模块之间的依赖关系 等),没有统一的模型维持业务和代码的一致性。
产品后期,用户或产品经理需求不断变更,工程师为了实现这些需求,代码到处修修改改。
最后产品困难重重,需求不断延期,线上bug不断。
2.3 事务脚本vs领域模型 (贫血模型 vs 充血模型)
事务脚本又称为贫血模型
领域模型有称为充血模型


事务脚本方式中,findContract包括了所有的商品合同的处理,巨大无比,一旦业务有变动,代码就需要就进行变动。
领域模型方式中,每个领域模型都有属性和方法,让每个类对象自己处理相关的业务,后期通过添加新的类进行扩展(实际上就是面向对象编程)。
2.4 DDD相关的概念

领域
领域是一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事方式,也是软件开发的目标范围。(就是整个系统所要做的事情)
领域驱动设计
领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。
子域
领域的范围太大,所以通常把整个领域拆分成多个子域。
限界上下文
在一个子域中,会创建一个概念上的领域边界,在这个边界中,任何领域对象都只表示特定于该边界内部的确切含义。这样的边界称为限界上下文。限界上下文和子域具有一对一的关系,用来控制子域的边界。
上下文映射图
不同的界限上下文,也就是不同的子系统或者模块之间会有各种的交互合作。DDD使用上下文映射图来设计这种交互。
实体
领域模型对象也称为实体,每个实体都是唯一的,具有一个唯一标识。
实体设计是DDD和核心所在,首先通过业务分析,识别出实体对象,然后通过相关的业务逻辑设计实体的属性和方法。(其实就是OOP)
值对象
值对象的一个特点是不变性,一个值对象创建以后就不能再改变了。
聚合
聚合是一个关联对象的和集合,我们将其作为一个单元来处理数据更改。每个集合都有一个根和一个边界。边界定义了聚合内部的内容。根是聚合中包含的单个特定实体。

2.5 DDD架构设计
DDD分层架构
领域实体的组合调用和事务控制在应用层。

DDD六边形架构
领域模型通过应用程序封装成一个相对比较对立的模块,而不同的外部系统则通过不同的适配器和领域模型交互,比如http、webservice、MQ 访问领域模型,只需为这些不同的访问接口提供不同的适配器就可以了。

DDD战略设计与战术设计
领域、子域、界限上下文、上下文映射图,这些是DDD的战略设计。
实体、值对象、聚合、CQRS、事件溯源,这些是DDD战术设计。
通过战略设计,划分模块和服务的边界及依赖关系,对微服务架构设计至关重要。
DDD可以只有战略设计(模块划分),没有战术设计(具体实现)。
3. 总结
虽然微服务已经成为行业内最火热的技术之一,但是很多情况下,我们都没有考虑清楚我们要从微服务架构中获得什么,是为了业务复用, 还是开发边界清晰,或者分布式集群提升性能。微服务架构落地的最大的障碍不是使用什么技术手段,而是能不能弄清楚业务,模块的分解,模块之间的依赖关系等。DDD为我们做系统的设计(组件模块划分,模块的边界,模块之间的依赖关系 等)提供了方法论与最佳实践,用DDD可以指导我们进行微服务架构落地。实际上领域模型,充血模型就是OOP,实体(对象)是数据+操作。为什么这些没有成为主流,因为DDD需要在系统设计的时候下很大的功夫,定义清楚模块、边界 等等,而大部分项目初期都是趋利的,需要快速落地,进行市场试错,等项目慢慢做大,发现已经不堪重负,模块混乱,相互依赖,牵一发动全身,最终不得不进行重构来还这技术债务。
评论