深入研究消息队列03 各消息队列架构对比
  dBFTbkVLMBge 2023年11月02日 26 0

10 RabbitMQ的架构设计与实现

系统架构

深入研究消息队列03 各消息队列架构对比_架构设计

RabbitMQ 由 Producer、Broker、Consumer 三个大模块组成。生产者将数据发送到 Broker,Broker 接收到数据后,将数据存储到对应的 Queue 里面,消费者从不同的 Queue 消费数据。

深入研究消息队列03 各消息队列架构对比_架构设计_02

协议和网络模块

深入研究消息队列03 各消息队列架构对比_架构设计_03

深入研究消息队列03 各消息队列架构对比_架构设计_04

主要包含 tcp_listener、tcp_acceptor、rabbit_reader 三个进程。如下图所示,RabbitMQ 服务端通过 tcp_listener 监听端口,tcp_acceptor 接收请求,rabbit_reader 处理和返回请求。本质上来看是也是一个多线程的网络模型。

深入研究消息队列03 各消息队列架构对比_架构设计_05

数据存储

RabbitMQ 的存储模块也包含元数据存储与消息数据存储两部分。如下图所示,RabbitMQ 的两类数据都是存储在 Broker 节点上的,不会依赖第三方存储引擎。我们先来看一下元数据存储。

深入研究消息队列03 各消息队列架构对比_系统架构_06

深入研究消息队列03 各消息队列架构对比_架构设计_07

深入研究消息队列03 各消息队列架构对比_系统架构_08

深入研究消息队列03 各消息队列架构对比_系统架构_09

深入研究消息队列03 各消息队列架构对比_架构设计_10

深入研究消息队列03 各消息队列架构对比_架构设计_11

队列索引负责存储、维护队列中落盘消息的信息,包括消息的存储位置、是否交付、是否 ACK 等等信息。队列索引是 Queue 维度的,每个 Queue 都有一个对应的队列索引。

深入研究消息队列03 各消息队列架构对比_系统架构_12

生产者和消费者

当生产者和消费者连接到 Broker 进行生产消费的时候,是直接和 Broker 交互的,不需要客户端寻址。客户端连接 Broker 的方式,跟我们通过 HTTP 服务访问 Server 是一样的,都是直连的。部署架构如下图所示

深入研究消息队列03 各消息队列架构对比_架构设计_13

深入研究消息队列03 各消息队列架构对比_系统架构_14

生产端发送数据不是直接发送到 Queue,而是直接发送到 Exchange。即发送时需要指定 Exchange 和 route_key,服务端会根据这两个信息,将消息数据分发到具体的 Queue。因为 Exchange 和 route_key 都是一个逻辑概念,数据是直接发送到 Broker 的,然后在服务端根据路由绑定规则,将数据分发到不同的 Queue 中,所以在客户端是没有发送生产分区分配策略的逻辑。其实从某种程度来看,Exchagne 和 Route 的功能就是生产分区分配的过程,只是将这个逻辑从客户端移动到了服务端而已

RabbitMQ 支持 Push(推)和 Pull(拉)两种模式,如果使用了 Push 模式,Broker 会不断地推送消息给消费者。不需要客户端主动来拉,只要服务端有消息就会将数据推给客户端。当然推送消息的个数会受到 channel.basicQos 的限制,不能无限推送,在消费端会设置一个缓冲区来缓冲这些消息。拉模式是指客户端不断地去服务端拉取消息,RabbitMQ 的拉模式只支持拉取单条消息。

深入研究消息队列03 各消息队列架构对比_系统架构_15

HTTP 协议支持和管控操作

深入研究消息队列03 各消息队列架构对比_系统架构_16

开启插件后,就可以通过 HTTP 接口实现生产、消费、集群的配置、资源的创建、删除等操作

11 RocketMQ架构设计与实现

 RocketMQ 在功能、稳定性、性能层面都比 RabbitMQ 的表现更好。所以我们一起来看看为什么吧

RocketMQ 系统架构

RocketMQ 由 Producer、NameServer、Broker、Consumer 四大模块组成。其中,NameServer 是 RocketMQ 的元数据存储组件。另外,在 RocketMQ 5.0 后,还增加了 Proxy 模块,用来支持 gRPC 协议,并为后续的计算存储分离架构做准备

深入研究消息队列03 各消息队列架构对比_系统架构_17

深入研究消息队列03 各消息队列架构对比_系统架构_18

协议和网络模块

在协议方面,如下图所示,RocketMQ 5.0 之前支持自定义的 Remoting 协议,在 5.0 之后,增加了 gRPC 协议的支持。

这是在 Proxy 组件上完成了对 gRPC 协议的支持,用的是第 03 讲的代理(Proxy)模式。即 Broker 依旧只支持 Remoting 协议,如果需要支持 gRPC 协议,那么就需要单独部署 Proxy 组件。

深入研究消息队列03 各消息队列架构对比_系统架构_19

在传输层协议方面,Remoting 和 gRPC 都是基于 TCP 协议传输的。Remoting 直接基于四层的 TCP 协议通信,gRPC 是基于七层的 HTTP2 协议通信,不过 HTTP2 底层也是基于 TCP,它们本质上都是应用层的协议

深入研究消息队列03 各消息队列架构对比_系统架构_20

gRPC架构

深入研究消息队列03 各消息队列架构对比_架构设计_21

gRPC 分为 Client 端和 Server 端,底层基于 HTTP2 通信,内置了编解码模块,也定义好了 Client 和 Server 之间的调用方式,同时支持 TLS 加密,是一个完整的 RPC 框架。所以我们可以看到它在底层已经实现了网络通信、协议的设计、编解码框架等所有基础的工作。从使用的角度来说,gRPC 提供了各个语言的开发库,只需要集成对应语言的开发库,即可完成网络模块的开发,很轻便

数据存储

深入研究消息队列03 各消息队列架构对比_架构设计_22

深入研究消息队列03 各消息队列架构对比_架构设计_23

深入研究消息队列03 各消息队列架构对比_架构设计_24

在底层的文件存储方面,并不是一个 MessageQueue 对应一个文件存储的,而是一个节点对应一个总的存储文件,单个 Broker 节点下所有的队列共用一个日志数据文件(CommitLog)来存储,和 RabbitMQ 采用的是同一种存储结构。存储结构如下图所示:

深入研究消息队列03 各消息队列架构对比_系统架构_25

深入研究消息队列03 各消息队列架构对比_系统架构_26

RocketMQ 不是按照主题或队列维度来清理数据的,而是按照节点的维度来清理的。原因和 RocketMQ 的存储模型有关,上面说到 RocketMQ 所有 Queue 的日志都存储在一个文件中,如果要支持主题和队列单独管理,需要进行数据的合并、索引的重建,实现难度相对复杂

生产者和消费者

RocketMQ 的客户端连接服务端是需要经过客户端寻址的。如下图所示,首先和 NameServer 完成寻址,拿到 Topic/MessageQueue 和 Broker 的对应关系后,接下来才会和 Broker 进行交互。

深入研究消息队列03 各消息队列架构对比_架构设计_27

深入研究消息队列03 各消息队列架构对比_系统架构_28

深入研究消息队列03 各消息队列架构对比_系统架构_29

深入研究消息队列03 各消息队列架构对比_架构设计_30

深入研究消息队列03 各消息队列架构对比_架构设计_31

深入研究消息队列03 各消息队列架构对比_系统架构_32

消息粒度负载均衡就是我们之前在第 08 讲讲到的共享消费模式,而队列粒度负载均衡就是独占消费模式。大部分情况下,我推荐你优先使用队列粒度负载均衡

深入研究消息队列03 各消息队列架构对比_系统架构_33

深入研究消息队列03 各消息队列架构对比_系统架构_34

Http协议的支持和管控

RocketMQ 的管控也是不支持 HTTP 协议的操作的。RocketMQ 的管控操作都是通过 Remoting 协议支持的,在 gRPC 协议中也不支持管控操作。即在 Broker 中,通过 Remoting 协议暴露不同的接口或者在 NameServer 中暴露 TCP 的接口,来实现一些对应的管控操作。

客户端 SDK 会集成调用服务端这些接口的逻辑。命令行工具就是通过客户端 SDK 来完成管控操作,也可以在代码中通过 SDK 来执行管控操作

深入研究消息队列03 各消息队列架构对比_架构设计_35

12 Kafka的架构设计与实现

Kafka的系统架构

深入研究消息队列03 各消息队列架构对比_系统架构_36

Kafka 由 Producer、Broker、ZooKeeper、Consumer 四个模块组成。其中,ZooKeeper 用来存储元数据信息,集群中所有元数据都持久化存储在 ZooKeeper 当中。

深入研究消息队列03 各消息队列架构对比_系统架构_37

从消息的生命周期来看,生产者也需要通过客户端寻址拿到元数据信息。客户端通过生产分区分配机制,选择消息发送到哪个分区,然后根据元数据信息拿到分区 Leader 所在的节点,最后将数据发送到 Broker。Broker 收到消息并持久化存储。消费端使用消费分组或直连分区的机制去消费数据,如果使用消费分组,就会经过消费者和分区的分配流程,消费到消息后,最后向服务端提交 Offset 记录消费进度,用来避免重复消费。

协议和网络模块

Kafka 服务端的网络层是基于 Java NIO 和 Reactor 来开发的,通过多级的线程调度来提高性能

数据存储

深入研究消息队列03 各消息队列架构对比_系统架构_38

深入研究消息队列03 各消息队列架构对比_架构设计_39

深入研究消息队列03 各消息队列架构对比_架构设计_40

深入研究消息队列03 各消息队列架构对比_系统架构_41

深入研究消息队列03 各消息队列架构对比_架构设计_42

生产者和消费者

深入研究消息队列03 各消息队列架构对比_架构设计_43

深入研究消息队列03 各消息队列架构对比_系统架构_44

深入研究消息队列03 各消息队列架构对比_架构设计_45

深入研究消息队列03 各消息队列架构对比_系统架构_46

HTTP 协议支持和管控

Kafka 内核是不支持 HTTP 协议的,如果需要支持,则需要在 Broker 前面挂一层代理。如 Confluent 开源的 Kafka Rest

深入研究消息队列03 各消息队列架构对比_系统架构_47

13 Pulsar的架构设计与实现

作为消息队列后起之秀的 Pulsar,因为其存算分离、多租户、多协议、丰富的产品特性、支持百万 Topic 等特点,逐渐为大家所熟知。从定位来看,Pulsar 希望同时满足消息和流的场景。从技术上来看,它当前主要对标的是 Kafka,解决 Kafka 在流场景中的一些技术缺陷,比如计算层弹性、超大分区支持等等。

系统架构

深入研究消息队列03 各消息队列架构对比_系统架构_48

深入研究消息队列03 各消息队列架构对比_系统架构_49

深入研究消息队列03 各消息队列架构对比_系统架构_50

协议和网络层

深入研究消息队列03 各消息队列架构对比_架构设计_51

深入研究消息队列03 各消息队列架构对比_架构设计_52

深入研究消息队列03 各消息队列架构对比_系统架构_53

深入研究消息队列03 各消息队列架构对比_架构设计_54

数据存储

深入研究消息队列03 各消息队列架构对比_系统架构_55

Pulsar 需要存储更多元数据,所以 Pulsar 对 ZooKeeper 造成的压力会更大。也正因为如此,Pulsar 才会支持可插拔的元数据存储框架,希望通过其他的存储引擎来缓解 ZooKeeper 的瓶颈

深入研究消息队列03 各消息队列架构对比_架构设计_56

深入研究消息队列03 各消息队列架构对比_架构设计_57

深入研究消息队列03 各消息队列架构对比_架构设计_58

生产者和消费者

深入研究消息队列03 各消息队列架构对比_系统架构_59

深入研究消息队列03 各消息队列架构对比_架构设计_60

深入研究消息队列03 各消息队列架构对比_系统架构_61

深入研究消息队列03 各消息队列架构对比_架构设计_62

HTTP 协议支持和管控

在访问层面,Pulsar 的管控操作和生产消费数据流操作是分开支持的。即数据流走的是自定义协议通信,管控走的是 HTTP 协议形式的访问。从访问上就隔离了管控和数据流操作,在后续的权限管理、客户端访问等方面提供了很多便利。

深入研究消息队列03 各消息队列架构对比_架构设计_63

深入研究消息队列03 各消息队列架构对比_系统架构_64

深入研究消息队列03 各消息队列架构对比_系统架构_65

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
dBFTbkVLMBge