2.1 微服务架构到底是什么

2.1.1 软件架构是什么, 为什么它如此重要

软件架构的定义

该定义来自卡耐基梅隆大学软件工程研究所的 Len Bass 及其同事:

  • 计算机系统的软件架构是构建这个系统所需要的一组结构, 包括软件元素, 它们之间的关系以及两者的属性

有点像 E-R 图.

软件架构的4+1视图模型

image.png

我玩过的游戏 <<缺氧>> 中也提供了不同视图:

  • 电路
  • 水管
  • 气管
  • 气体分布
  • 温度

image.png

以前我对架构抱有高大上的想法 (银弹), 但现实是复杂的.

每个视图的目的:

image.png

场景:

  • 负责把视图串联在一起

为什么架构如此重要

image.png

架构是如何影响质量属性的?

2.1.2 什么是架构的风格

David Garlan 和 Mary Shaw 定义了如下架构风格:

image.png

  • 有限的元素 (组件)
  • 关系 (连接器)
  • 组合它们的一组约束

4+1视图模型描述了软件架构不用方面, 而架构风格是视图模型的实例?

分层式架构风格

分层架构将软件元素按 “层” 的方式组织. 每个层都有明确定义的职责. 分层架构还限制了层之间的依赖关系. 每一层只能依赖于紧邻其下方的层 (如果严格分层) 或其下面的任何层.

三层架构是应用与逻辑视图的分层架构, 它将应用程序的类组织到以下层中:

image.png

分层架构风格的弊端:

image.png

关于架构风格的六边形

六边形架构风格选择以业务逻辑为中心的方式组织逻辑视图.

此架构的一个关键特性和优点是业务逻辑不依赖于适配器, 相反, 各种适配器都依赖业务逻辑.

image.png

业务逻辑具有一个或多个端口 (port). 端口定义了一组操作, 关于业务逻辑如何与外部交互:

  • 入站端口是业务逻辑公开的 API, 它使外部应用程序可以调用它
    • 一个实例是服务接口, 定义服务的公共方式
  • 出站端口是业务逻辑调用外部系统的方式
    • 一个实例是存储库接口, 定义数据访问操作的集合

业务逻辑的周围是适配器:

  • 入站适配器: 通过调用入站端口来处理来自外部的请求
    • Spring MVC Controller
    • 订阅消息的消息代理客户端
  • 出站适配器: 实现出站端口, 并通过调用外部应用程序或服务处理来自业务逻辑的请求
    • 数据访问对象 (DAO)
    • 代理类

2.1.3 微服务架构是一种架构风格

  • 单体架构是一种架构风格, 它的实现视图是单个组件: 单个可执行文件或 WAR 文件

image.png

  • 微服务架构也是一种架构风格. 它的实现视图由多个组件构成: 一组可执行文件或 WAR 文件
    • 它的组件是服务
    • 连接器是使这些服务能够协作的通信协议
    • 每个服务都有自己的逻辑视图架构, 通常是六边形架构

image.png

image.png

微服务架构强加的一个关键约束是服务松耦合.

  • 服务之间的协作方式存在一定限制

什么是服务

服务是一个单一的, 可独立部署的软件组件, 它实现了一些有用的功能.

image.png

  • 典型的服务往往都具有六边形架构

什么是松耦合

服务之间的交互采用 API 完成, 这样做就封装了服务的实现细节.

  • 数据库私有访问
  • 数据共享困难

共享类库的角色

  • 要注意避免引入耦合

可能的例子:

image.png

  • 不太会变的功能应该打包成共享库, 以便各个服务来引用, 避免重复实现
  • 经常变更的功能应以服务来实现

服务的大小并不重要

  • 大小不是一个重要的考虑因素
  • 由小团队开发的服务, 交付时间短, 与其他团队协作少

2.2 为应用程序定义微服务架构

定义架构的三步式流程 (大概的方法):

  • 需要不断迭代, 创新

image.png

  • 第一步: 将应用程序的需求提炼为各种关键请求
  • 第二步: 确定如何分解服务, 两种策略 (都是非技术概念分解和设计)
    • 定义与业务能力相对应的服务
    • 围绕领域驱动设计的子域来分解和设计服务
  • 第三步: 确定每个服务的 API, 还有
    • 服务的写作方式
    • 进程间通信机制

服务分解的障碍:

  • 网络延迟
  • 服务之间的同步通信降低了可用性
  • 维护跨服务的数据一致性
  • 上帝类

image.png

可以研究 go-micro 是如何解决的.

2.2.1 识别系统操作

起点是应用程序的需求, 包括用户故事及其相关的用户场景.

两步式流程:

  1. 抽象领域模型, 提供描述系统操作的词汇表
  2. 确定系统操作, 根据领域模型描述每个系统操作的行为

image.png

创建抽象领域模型

  • 第一步: 为应用程序描绘一个抽象的领域模型, 能够为描述系统操作定义一些词语
    • 通过用户故事, 提炼一些类

image.png
类的作用:

image.png

定义系统操作

两种类型的系统操作:

  • 命令型: 创建, 更新, 删除数据
  • 查询型: 查询, 读取数据

识别系统指令的切入点是分析用户故事和场景中的动词.

系统命令举例:

image.png

命令规范定义了命令对应的参数, 返回值和领域模型类的行为.

行为规范中包括前置条件, 后置条件.

createOrder() 系统操作规范:

image.png

acceptOrder() 系统操作规范:

image.png

2.2.2 根据业务能力进行服务拆分

创建微服务架构的策略之一: 采用业务能力进行服务拆分.

  • 业务能力是指一些能够为公司 (或组织) 产生价值的商业活动

image.png

业务能力定义了一个组织的工作

组织的业务能力通常是指这个组织的业务是做什么, 它们通常都是稳定的. 组织采用何种方式来实现它的业务能力, 是随时间不断变化的.

  • “兑现支票”: 支票 -> ATM -> 智能手机

识别业务能力

一个组织有哪些业务能力, 是通过对组织的目标, 结构和商业流程的分析得来的.

  • 业务能力通常集中在特定的业务对象上
  • 能力通常可以分解为子能力

业务能力规范包括:

  • 输入
  • 输出
  • 服务等级协议 (SLA)

FTGO 的业务能力:

image.png

从业务能力到服务

决定将哪个级别的能力层次结构映射到服务是一个非常主观的判断.

image.png

2.2.3 根据子域进行服务拆分

领域驱动设计是构建复杂软件的方法论:

  • 面向对象
  • 领域模型. 领域词汇表, DDD 也称为通用语言 (Ubiquitous language)

image.png

DDD 的两个重要概念:

  • 子域
  • 限界上下文, 包括实现这个模型的代码集合

可以通过 DDD 的方式定义子域, 并把子域对应为每一个服务:

image.png

2.2.4 拆分的指导原则

面向对象设计的一些原则可以用于知道微服务架构的设计工作.

单一职责原则

Single Responsibility Principle, SRP

改变一个类应该只有一个理由.

闭包原则

Common Closure Principle, CCP

在包中包含的所有类应该是对同类的变化的一个集合, 也就是说, 如果对包做出修改, 需要调整的类应该都在这个包之内.

  • <<面向对象设计的原则>> Bob Martin

2.2.5 拆分单体应用为服务的难点

网络延迟

解决方案:

  • 在一次往返中获取多个对象
  • 把多个相关的服务组合在一起

同步进程间通信导致可用性降低

服务之间的调用是个链条, 如果其中某个服务出现问题, 那么用户的某个操作就会失败.

  • 使用异步解耦

在服务之间维持数据一致性

需要实现事务操作, 如果要更新两个或更多服务的数据, 要么都成功, 要么都失败.

  • 两阶段提交 (two phase commit)
  • Saga (最终一致)

获取一致的数据视图

也是类似事务, 但不会带来真正问题 (读操作).

上帝类阻碍了拆分

上帝类是在整个应用程序中使用的全局类.

传统建模技术创建的 Order 类结构:

image.png

解决方案是使用 DDD, 并将每个服务视为具有自己的领域模型的单独子域:

  • 每个服务有自己领域模型及其对应的 Order 类

Order -> Delivery:

image.png

Order -> Ticket:

image.png

Order -> 新 Order:

image.png

  • 用事件驱动机制 Saga 来维护服务之间的一致性

2.2.6 定义服务 API

存在服务 API 的两个原因:

  • 某些操作对应系统操作
  • 存在一些其他操作用以支持服务之间的写作

定义服务 API 的过程:

  1. 系统操作映射到服务
  2. 确定服务是否需要与其他服务写作以实现系统操作

把系统操作分配给服务

  • 确定哪个服务是请求的初始入口点

image.png

确定支持服务协作所需要的 API

前置条件, 后置条件:

image.png

  • REST 等同步通信机制
  • 消息代理的异步消息
  • 自包含服务
  • CQRS 模式

本章小结

image.png