微服务架构设计模式
2021-11-16 16:54:57 13 举报
AI智能生成
微服务架构设计模式
作者其他创作
大纲/内容
软件架构
定义: 计算机系统的软件架构是构建这个系统所需要的一组结构,包括软件元素, 他们之间的关系以及两者之间的属性
4+1 视图模型
逻辑视图
主要是整个系统的抽象结构表述,关注系统提供最终用户的功能,不涉及具体的编译即输出和部署,通常在UML中用类图,交互图,时序图来表述,类似与我们采用OOA的对象模型
物理视图
物理视图通常也叫做部署视图(deploymentview),是从系统工程师解读系统,关注软件的物流拓扑结,以及如何部署机器和网络来配合软件系统的可靠性、可伸缩性等要求。
进程视图
从过程角度,描述系统的并发和同步设计。旨在解决进程、线程、并发、同步、通信等方面的问题;
开发视图
描述软件在开发环境下的静态组织,从程序实现人员的角度透视系统,也叫做实现视图(implementation view)。开发视图关注程序包,不仅包括要编写的源程序,还包括可以直接使用的第三方SDK和现成框架、类库,以及开发的系统将运行于其上的系统软件或中间件, 在UML中用组件图,包图来表述。
用例场景+1
用例视图(Use Cases View),最初称为场景视图,关注最终用户需求,为整个技术架构的上线文环境.通常用UML用例图和活动图描述。
重要性
功能性需求
主要包括程序的意义, 用例或者用户故事等
非功能性需求
能力的需求, 包括不限于可维护性/可伸缩性/可测试性/可扩展性/可部署性
风格表现方式
分层式
将软件元素按照层次来进行划分, 例如表现层/业务层/持久层等
六边形式
选择将业务逻辑作为核心层的一种逻辑视图, 六个边包括不局限于各种出入站的适配器等. 例如入站包括: RestFul/Soap 服务/Controller适配器/消息接收器等, 出站包括: 存储接口/其他服务调用器/消息发送器等等;
实现风格
单体应用
定义: 将应用程序构建为单个可执行和可部署的组件
微服务
定义
微服务: 将应用程序构建为松耦合,可独立部署的一组服务
服务: 是一个单一的,可独立部署的软件组件, 实现了一些有用的功能.
松耦合: 服务之间的交互采用API完成, 封装了服务内部的细节.
备注
如何区分共享库?
如果是底层通用的不太可能变化的东西, 可以使用共享库功能. 例如一些公关的Util包, 或者一些第三方的框架, 甚至是业务上一些底层没有变更需求的公关组件.
服务的大小重要否?
微服务这个术语可能让你错误的聚焦在微上, 它似乎暗示了服务应该很小. 事实上这并不是一个考虑的主要因素, 更多的要从团队开发角度上, 交付的时间上, 与其他团队协作最少工作上, 其他还包括测试上等.
微服务架构的实现
定义
和所有软件开发一样, 第一架构也是一项艺术而非技术, 现实世界中这也是一个不断迭代和持续创新的过程.
识别系统操作
系统操作是应用程序必须处理的请求的一种抽象描述, 它既可以是更新数据的命令, 也可以是查询数据的操作. 具体就是描述服务之间协作方式的架构场景.
拆分服务
根据业务能力拆分
业务能力一般类似于角色-能力的角度, 例如外卖送餐服务的角色为送餐员, 其能力是取餐/送单/返回等.
根据领域概念拆分
领域概念来自DDD的划分, 将领域切分为一个一个的子域.
拆分原则
单一原则
小的/内聚的/仅仅含有单一职责的服务, 这样设计可以缩小服务的大小, 并提升其稳定性.
闭包原则
相同功能的一组组件都应该在一个服务内, 这个可以控制服务的数量. 理想情况下, 一个变更只会影响一个团队和一个服务. 其是解决分布式单体这种可怕的反模式的法宝.
拆分难点
网络延迟
同步进程间通信可能导致可用性降低
服务之前维持数据的一致性, 例如分布式事务
获取一致的数据视图, 一致性差导致的数据瞬时差异
公共类/上帝类, 造成了拆分困难.
事件溯源
概念
这个是一种以事件为中心的编写业务逻辑和持久化领域对象的方法, 通常情况下可以和领域事件协调一起
好处
可靠地发布领域事件
保留历史, 可以作为行为分析, 或者数据审计使用
最大限度的可以减少对象与关系的阻抗失调问题
主要是说BO对象与关系表无法映射的时候的差异问题
缺点
学习曲线高
消息传递的问题, 造成复杂度高
事件演化分析, 需要有一定的能力
删除数据/ 查询历史的事件, 需要一定的技术基础
发布事件方式
第三方程序轮询事件表/ 事件的集合
通过数据库本身的事务日志拖尾机制, 或者类似mysql的bin log模式
设计模式
聚合器微服务设计模式
聚合器调用多个服务实现应用程序所需的功能。它可以是一个简单的 WEB 页面,将检索到的数据进行处理展示。它也可以是一个更高层次的组合微服务,对检索到的数据增加业务逻辑后进一步发布成一个新的微服务,这符合 DRY 原则。另外,每个服务都有自己的缓存和数据库。如果聚合器是一个组合服务,那么它也有自己的缓存和数据库。聚合器可以沿 X轴 和 Z轴 独立扩展。
代理微服务设计模式
在这种情况下,客户端并不聚合数据,但会根据业务需求的差别调用不同的微服务。代理可以仅仅委派请求,也可以进行数据转换工作。
链式微服务设计模式
在这种情况下,服务A 接收到请求后会与 服务B 进行通信,类似地,服务B 会同 服务C 进行通信。所有服务都使用同步消息传递。在整个链式调用完成之前,客户端会一直阻塞。因此,服务调用链不宜过长,以免客户端长时间等待。
分支微服务设计模式
这种模式是聚合器模式的扩展,允许同时调用两个微服务链,如下图所示
数据共享微服务设计模式
自治是微服务的设计原则之一,就是说微服务是全栈式服务。但在重构现有的“单体应用(Monolithic Application)”时,SQL 数据库反规范化可能会导致数据重复和不一致。因此,在单体应用到微服务架构的过渡阶段,可以使用这种设计模式,如下图所示
异步消息传递微服务设计模式
虽然 REST 设计模式非常流行,但它是同步的,会造成阻塞。因此部分基于微服务的架构可能会选择使用消息队列代替 REST 请求/响应,如下图所示
查询模式
外部化配置模式
业务逻辑设计
组织模式
事务脚本
抛弃OO的思想, 直接面向过程的一种设计方式.Matrtin 曾经提到过这个, 类似使用存储过程代替服务来直接处理.
领域模型
将业务逻辑组织为由具有状态和行为的类构成的对象模型.
领域驱动设计
基本元素
实体(Entity)
具有持久化ID的对象
值对象
工厂
存储库(Repository)
服务
实现不属于实体或者值对象的业务逻辑对象
聚合设计模式
概念: 将领域模型组织为聚合的集合, 每个聚合都是可以作为一个单元进行处理的一组对象构成的图
规则
只引用聚合的根
说白了只能通过跟对象引用别的聚合的根, 或者被引用
聚合间的引用必须使用主键
没有对象引用了, 但是我觉得可以使用类似ID/UUID/Code等婉转的方式
一个事务中, 只能创建和更新一个聚合
如果使用Saga, 那么每一个聚合都是一个参与者.
颗粒度
这个按照你的团队成熟度/业务成熟度/实际情况等考虑
领域事件
概念: 领域事件是聚合发生变化的事情, 通常代表着状态的变化.
识别方法
事件风暴模式, 包括头脑风暴/识别事件发生机制/识别聚合
发布方式
通过聚合主动发送事件给订阅者, 类似Observer模式
通过聚合根保存这些事件, 由外部或者其他机制来检索
例子
观测性模式
开发安全相关
进程间通信
概述
交互方式
一对一
请求/响应
单个客户端发起请求并等待返回, 可能导致线程堵塞.
异步请求/响应
单个客户端发起异步请求, 服务器异步返回响应.
单向通知
单个客户端方发起请求, 不期望服务器端返回
一对多
发布/订阅
客户端发布消息, 被0-N个感兴趣的服务订阅
发布/异步响应
客户端发布消息, 然后等待从特定的的服务发回的响应. 类似两个消息通道..
API定义
api优先原则, 例如使用RAML或者Swagger等提前定义好API的规范, 保证前后端的并行工作
API的版本规范, 可以使用路径加上版本号, 或者HttpHeader中加入verison等机制
向后兼容需要考虑健壮性原则, 避免产生升级壁垒
消息格式
文本
JSON/XML
二进制
Protocol Buffers/Avro/Thrift
同步通信
RPI概念
RPI是远程过程调用模式
REST
概念
RESTful是这一种开发的风格, 最早来自Roy的论文
另外一个关键性概念是 资源
成熟度模型
Level 0
本层级的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。
Level 1
Level 1 层级的 API 引入了资源的概念。要执行对资源的操作,客户端发出指定要执行的操作和任何参数的 POST 请求。
Level 2
Level 2 层级的 API 使用 HTTP 语法来执行操作,譬如 GET 表示获取、POST 表示创建、PUT 表示更新。如有必要,请求参数和主体指定操作的参数。这能够让服务影响 web 基础设施服务,如缓存 GET 请求。
Level 3
Level 3 层级的 API 基于 HATEOAS(Hypertext As The Engine Of Application State)原则设计,基本思想是在由 GET请求返回的资源信息中包含链接,这些链接能够执行该资源允许的操作。例如,客户端通过订单资源中包含的链接取消某一订单,GET 请求被发送去获取该订单。HATEOAS 的优点包括无需在客户端代码中写入硬链接的 URL。此外,由于资源信息中包含可允许操作的链接,客户端无需猜测在资源的当前状态下执行何种操作。(包括字描述和下次动作的概念)
优缺点
好处
简单好用上手快
工具和浏览器扩展支持方便测试
使用http协议对于防火墙比较友好
行为和资源分离,更容易理解。
弊端
直接的请求/响应模式, 可用性需要双方保持在线保证
客户端必须要支持URL的位置概念, 否则而需要服务发现来定位
多个请求中获取一个资源, 概念上有些不匹配
映射到HTTP动词上很有挑战, 包括返回的HTTP状态码也是痛点
gRPC
概念
一种基于二进制消息的协议, 有一个或者多个服务的请求和响应定义组成, 类似java的接口. 除了支持简单的请求/响应, 还支持流式的RPC, 支持双向流入流出方式.
优缺点
好处
设计复杂的操作的API比较方便
高效/紧凑的进程间通信, 大量通信的时候比较有优势
支持双向流的模式
支持各种异构语言的实现, 和相互调用
弊端
学习成本, 且上手需要学习IDL规范
防火墙可能不支持HTTP/2的协议
调试和跟踪二进制没有文本方便
断路器模式
概念
一个远程过程调用的代理, 再连续失败次数超过一定阈值后, 这个代理会拒绝掉其他访问该服务的调用. 例如Hystrix
处理方式
网络超时, 避免无限的堵塞
限制请求的数量, 使用流量桶/令牌桶模式
断路器模式, 根据成功失败的数量, 来进行限制
服务发现
概念
其关键性组件是服务注册表, 包含服务实例的网络位置信息额一个数据库
主要方式
应用层服务发现模式
自注册和客户端发现
平台层服务发现模式
Docker和Kubernetes 有内置的服务注册表和服务发现能力, 可以使用DNS和虚拟IP进行路由.
第三方注册/服务端发现
异步通信
消息类型
文档
仅仅包含数据的通用消息, 接受者知道如何解析它
命令
等同于使用RPC做调用, 包含具体的操作和参数
事件
表示发送方发生了具体的时间, 通常情况下是领域事件, 例如说Order的状态变更
例子
通道类型
点对点通道
一方传给另一方, 一对一的通讯
发布订阅通道
一对多的交互模式
消息代理
无代理架构
服务可以直接交换消息, 例如ZeroMQ就是一种技术, 也是规范. 可以实现Tcp, Unix风格的Socket和多播等
有代理架构
消息代理是中介节点, 好处是发送方不需要直接接受方的位置, 同时有缓冲的和持久化的功能.包括ActiveMQ/RabbitMQ/Kafka等
消息顺序
现在消息代理Kafka和Aws Kinesis使用的是分片/分区通道 发送消息头部制定分区键, 这样可以通过hash来计算进行选择. SQS使用的也是分组的概念, 使用消息分组ID来进行分区.
重复消息
幂等消息处理
程序本身进行处理, 根据业务的要求进行代码的编写
重复消息丢弃
例如: 使用数据库的唯一约束进行丢弃, 每次接受一条消息插入到数据库, 插入失败的则丢弃
事务性消息
使用数据库表作为消息队列
首先插入消息到数据库表, 然后利用其它的消息中继程序读取消息再发送.
两种方式
1. 使用消息中继轮询消息表, 进行数据的发送
2. 使用事务日志拖尾机制, 例如每次事务提交都在拖尾的事务日志中添加一个条目, 事务日志挖掘其可以读取, 再转换为消息发送. 例如: Debezium和LinkedIn Databus等
异步交互
0 条评论
下一页