《微服务架构设计模式》-学习总结03

本篇主要总结第三章:微服务架构中的进程间通信

微服务的交互方式

在不讨论消息具体实现的情况下,作者从不同维度先对进程间通信的交互方式进行了分类和归纳。

  • 客户端与服务的交互方式(维度一)
    • 一对一:每个客户端请求由一个服务实例来处理
    • 一对多:每个客户端请求由多个服务实例来处理
      • 发布/订阅
      • 发布/异步响应
  • 客户端与服务的交互方式(维度二)
    • 同步模式:客户端需要服务端实时响应,等待响应的过程可能导致阻塞
    • 异步模式:客户端请求不会阻塞进程,服务端的响应可以是非实时的

微服务架构中定义API

1. API优先设计:作者认为API是软件开发的中心,推荐在微服务中使用API优先设计的开发方式。开发人员先把客户端-服务端之间的API接口定义好之后,再开始各自的编程。

2. API的变更:微服务架构中,API一旦确定就下来,在更新API时必须确保旧新版本API的兼容性。因此,引入API版本控制——语义化版本控制

语义化版本控制,由3部分组成:MAJOR.MINOR.PATCH。递增版本号规则:

  • MAJOR:对API进行不兼容的更改时
  • MINOR:对API进行后向兼容的增强时
  • PATCH:进行后向兼容的错误修复时

3.后向兼容的更改

在微服务架构中对API尽量只进行后向兼容的更改:

  • 添加可选属性
  • 向响应添加属性
  • 添加新操作

4.非后向兼容的更改

如果必须进行非后向兼容的更改,需要同时支持新旧版本的API,直到所有客户端都升级到新的API。可以通过以下方式实现:

  • 在URL中嵌入版本号
  • 使用HTTP的内容协商机制,在MIME中包含版本号

消息的格式

消息的格式可分为两大类:文本和二进制

  • 文本
    • JSON、XML
    • 文本消息的弊主要是消息冗长,必须传输属性名造成额外开销
  • 二进制
    • Protocol Buffers、Avro

基于同步远程过程调用模式的通信

作者主要介绍了REST和gRPC,感觉作者更倾向于gRPC。

  • REST
    • good
      • 简单
      • 可以用浏览器或curl命令直接测试HTTP API
      • 直接支持请求/响应方式的通信
      • HTTP对防火墙友好
      • 不需要中间代理,简化了系统架构
    • bad
      • 只支持请求/响应方式的通信
      • 可能导致可用性降低。在REST API调用期间都必须保持在线,没有代理缓冲消息
      • 客户端必须知道服务器的URL
      • 在单个请求中获取多个资源具有挑战性
      • 有时很难将多个更新操作映射到HTTP动词
  • gRPC
    • 指定二进制消息格式protocol buffers
    • good
      • 设计具有复杂更新操作的API非常简单
      • 高效、紧凑的进程间通信机制,尤其是在交换大量消息时
      • 支持在远程过程调用和消息传递过程中使用双向流式消息方式
      • 实现了客户端和用各种语言编写的服务端之间的互操作性
    • bad
      • 与基于REST/JSON的API机制相比,JavaScript客户端使用gRPC的API需要做更多工作
      • 旧式防火境况可能不支持HTTP/2

同步通信必须处理局部故障以提高可用性,作者介绍了断路器模式。

断路器:一个远程过程调用的代理,在连续失败次数超过指定阈值后的一段时间内,这个代理会立即拒绝其他调用。

同时分享了Netflix的经验,同步调用一个服务时,客户端需要这样的机制增加健状性:

  • 网络超时:等待响应时设定一个超时
  • 限制客户端向服务器发出请求的数量:设置向特定服务发起请求的上限,如果请求达到上限,很可能发起更多的请求也无济于事,此时应该限制发起新的请求,立刻失败。
  • 断路器模式:监控客户端发出请求的成功和失败数量,如果失败的比例超过一定的阈值,就启动断路器,让后续的调用立刻失效。在经过一定的时候后,客户端应该继续尝试,如果调用成功则解除断路器。

服务发现

在使用同步远程过程调用中,必须使用服务发现机制,以获取需要调用服务的网络位置。作者介绍了服务发现的分类,并推荐使用平台层服务发现模式。

应用层服务发现模式

  • 自注册:服务实例向服务注册表注册自己
  • 客户端发现:客户端从服务注册表检索可用服务实例的列表,并在它们之间进行负载平衡。

平台层服务发现模式

部署平台为每个服务提供DNS名称、虚拟IP地址和解析为VIP地址的DNS名称。客户端向DNS名称和VIP发出请求,部署平台自动将请求路由到其中一个可用服务实例。

  • 第三方注册模式:由第三方负责处理注册,而不是服务本身向服务注册表注册自己
  • 服务端发现模式:客户端不再需要查询服务注册表,而是向DNS名称发出请求,对该DNS名称的请求被解析到路由器,路由器查询服务注册表对请求进行负载均衡

基于异步消息模式的通信

作者的观点是,理想情况下,微服务架构下的通信应该尽可能使用异步消息模式,以提高系统的可用性。下面是关于消息的相关概念和定义:

消息传递

发送方将消息写入通道,接收方从通道读取消息。

  • 文档
  • 命令:一条等同于RPC请求的消息。
  • 事件

消息通道

  • 点对点
  • 发布-订阅

消息代理

  • Apache ActiveMQ
  • RabbitMQ
  • Apache Kafka

异步API规范

服务的异步API规范必须指定消息通道的名称、通过每个通道交换的消息类型及格式。

  • 异步操作
    • 请求/异步响应式API
    • 单向通知API
  • 事件发布

基于代理的消息

作者推荐微服务架构下使用基于代理的消息,一是因为发送方不需要知道接收方的网络位置;二是因为消息代理可以缓冲消息直到消息被接方处理。选择消息代理时,需要考虑以下各种因素:

  • 支持的编程语言
  • 支持的消息标准
  • 消息排序:消息保序
  • 投递保证
  • 持久性:是否持久化到磁盘
  • 耐久性:如果接收方重新连接到消息代理,它是否会收到断开连接时发送的消息
  • 可扩展性
  • 延迟
  • 竞争性(并发)接收方:消息代理是否支持并发接收方

消息代理的好处和弊端

Good

    • 松耦合
    • 消息缓存
    • 灵活的通信
    • 明确的进程间通信
  • Bad
    • 潜在的性能瓶颈
    • 潜在的单点故障
    • 额外的操作复杂性

处理并发和消息顺序

  • 消息通道分片:通过分片消息通道的方式来扩展接收方,同时又确保消息被处理的顺序。

处理重复消息

  • 幂等消息处理器:被相同参数多次调用时,不会产生额外的效果。
  • 跟踪消息并丢弃重复消息

事务性消息

事务性消息是指在更新数据库的事务中发布消息:更新数据库和消息发布必须以原子方式进行,否则系统可能昝于不一致状态。

  • 使用数据库表作为消息队列
    • 事务性发件箱模式:使用数据库表作为临时消息队列。发送消息的服务有一个OUTBOX数据库表。作为创建、更新和删除业务对象的数据库事务的一部分,服务通过将消息插入到OUTBOX表中来发送消息
      • 轮询发布数据:通过轮询数据库中的发件箱来发布消息。
  • 使用事务日志拖尾模式发布事件:通过拖尾事务日志发布对数据库所做的更改。

异步消息提高可用性

进程间通信机制与系统可用性之间的关系。同步机制的可用性相对较低,应该尽可能选择异步通信机制来处理服务之间的调用。

  • 同步消息会降低可用性
    • 最大化一个系统的可用性,就应该设法最小化系统的同步操作量
  • 消除同步交互
    • 使用异步交互模式
    • 复制数据
    • 先返回响应,再完成处理

学习总结

整章学习下来,感觉作者比较推崇基于消息代理的异步通信模式。主要原因是提高系统的可用性,降低通信过程中的耦合度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值