充当服务之间的中介.

image.png

3.3.1 什么是消息传递

关于消息

组成:

  • 消息头: key-value 形式
    • 发件人
    • 唯一消息 ID
    • 回复消息的通道
  • 消息体
    • 格式: 文本或二进制
    • 类型
      • 文档
      • 命令
      • 事件

关于消息通道

image.png

消息通道的类型:

  • 点对点通道, 命令式消息常用
  • 发布-订阅通道, 事件式消息常用

3.3.2 使用消息机制实现交互方式

消息机制可以实现所有交互方式.

实现请求/响应和异步请求/响应

区别:

  • 对于请求/响应, 客户端期望服务立即响应
  • 而对于异步请求/响应, 则没有这样的期望

异步实现:

  • 请求通道是服务创建的
  • 回复通道是客户端创建的

image.png

实现单向通知

与图3-8类似, 只是服务端不回复消息.

  • 点对点

实现发布/订阅

与图3-8类似.

实现发布/异步响应

组合:

  • 一对多关系 (发布-订阅)
  • 请求/响应

3.3.3 为基于消息机制的服务 API 创建 API 规范

服务的异步 API 规范需指定:

  • 消息通道的名称
  • 通过每个通道交换的消息类型及其格式

image.png

记录异步操作

可以使用以下两种不同交互方式调用服务的操作:

image.png

记录事件发布

服务可以使用发布/订阅的方式对外发布事件.

API 规范:

  • 事件通道
  • 服务发布到通道的事件式消息的类型和格式

3.3.4 使用消息代理

这里的消息代理指消息中间件.

有无代理的区别:

image.png

无代理消息

ZeroMQ

好处:

image.png

弊端:

image.png

基于代理的消息

好处:

  • 发送方不需要知道接收方的网络位置
  • 消息代理缓冲消息, 直到接收方能够处理它们

开源消息代理:

  • Apache ActiveMQ
  • RabbitMQ
  • Apache Kafka
  • AWS Kinesis

选择消息代理需要考虑的因素:

image.png

image.png

使用消息代理实现消息通道

不同实现:

image.png

基于代理的消息的好处和弊端

好处:

image.png

弊端:

image.png
image.png

3.3.5 处理并发和消息顺序

确保每个消息只被处理一次, 并且按照发送的顺序来处理.

业务上产生的消息是有逻辑顺序的, 在交给接收方处理时也要按照顺序处理.

使用分片 (分区) 保证顺序:

image.png

本质是利用分片, 将相同 shard-key 分配给同一实例, 这样业务上顺序的消息会被同一实例顺序处理.

3.3.6 处理重复消息

保证有且仅有一次的消息传递通常成本很高, 大多数消息代理承诺至少成功传递一次消息.

处理重复消息的方法:

  • 编写幂等消息处理程序
  • 跟踪消息并丢弃重复项

编写幂等消息处理器

满足幂等的消息处理程序可以被放心地执行多次, 只要消息代理在重新传递消息时保持相同的消息顺序

image.png

跟踪消息并丢弃重复消息

使用 message id 跟踪已处理消息:

  • 如果使用数据库, 那么保存 message id 和业务数据可以在一个事务中

image.png

  • 如果使用 NoSQL, 那么保存 message id 的表应该放在应用程序中

3.3.7 事务性消息

image.png

操作数据库和发送消息可能要组成事务来执行.

分布式事务.

使用数据库表作为消息队列

image.png

image.png

通过轮询模式发布事件

让 MessageRelay 轮询 OUTBOX 表.

image.png

使用事务日志拖尾 (tailing) 模式发布事件

让 MessageRelay 拖尾数据库的事务日志文件 (提交日志).

image.png

image.png

实际的应用案例和实现:

image.png

3.3.8 消息相关的类库和框架

直接使用消息代理的客户端库的问题:

image.png

作者在本书中使用了他开发的框架 Eventuate Tram.

Eventuate Tram 支持的交互方式:

  • 发送, 接收消息的 API
  • 异步请求/响应
  • 领域事件发布

Eventuate Tram 实现的两个重要机制:

  • 事务性消息机制: 将消息作为数据库事务的一部分发布
  • 重复消息检测机制: 支持消息接收方检测并丢弃重复消息

基础消息 API

  • MessageProducer: 发布消息
  • MessageConsumer: 订阅消息

用于异步请求/响应和领域事件发布.

领域事件发布 API

  • DomainEventPublisher: 发布事件
  • DomainEventDispatcher: 消费事件

基于命令/回复的消息

同步的?

  • CommandProducer: 发送命令
  • CommandDispatcher: 接收命令