Kubernetes 上的 RabbitMQ
RabbitMQ是一款开源消息代理软件,它实现了多种消息传递协议,最初是AMQP(高级消息队列协议),此外还包含基于 Web 的消息传递协议,例如STOMP(简单文本导向消息传递协议)、MQTT(消息队列遥测传输)和WebSocket,用于解耦共享异步数据的应用程序。RabbitMQ 不仅因其稳健性和维护良好的开源特性而成为极具吸引力的消息传递系统选择,还因其易用性和配置性而脱颖而出。在创建我们的第一个 RabbitMQ 实例和集群之前,让我们先来了解一些关于消息传递的基本概念,并看看一些常见的用例。
ℹ️ 截至撰写本文时,最新的 RabbitMQ 版本是。请参阅此处的
3.13.2
更改日志。
基础知识
同步与异步消息传递
在同步消息传递中,发送者需要等待响应才能继续处理,这可能会导致瓶颈或效率低下。另一方面,异步消息传递允许在没有立即响应的情况下发送消息,从而释放了发送者的资源,打破了应用程序或微服务之间的同步关系(称为)decoupling
。
消息系统在需要异步通信的场景中表现出色。对于交换大量消息且依赖可靠交付的解耦应用程序来说,消息系统是使用消息系统的最佳选择。从distributed systems
到microservices architectures
,event-driven setups
像 RabbitMQ 这样的消息代理能够促进跨多种不同技术架构的无缝通信。
生产者和消费者📲
最简单的消息传递图如下所示:Producer - Queue - Consumer
消息代理🎛️
消息代理是消息系统的核心组件,负责协调各种消息核心实体(例如连接、通道、队列和交换等)的管理。
作为中心枢纽,该代理涵盖 RabbitMQ 的所有功能,从集群、镜像到 GUI 和插件管理。它遵循开放标准 AMQP 协议进行消息传输,方便客户端与代理本身之间的通信。
其他关键组件🧩
生产者应用程序connection
通过 与消息代理建立连接TCP connection
。在此连接中,multiple channels
可以创建 ,用于在逻辑上分隔数据流。每个通道都用于将数据传输到queue
。这些队列充当中间存储,连接consumer apps
可以从中消费消息。如果Pub/Sub messaging pattern
使用 ,则exchange
可能还存在 。
RabbitMQ 还引入了虚拟主机的概念(vhosts)
来划分和隔离代理内的消息传递资源,使得不同的环境或应用程序能够在同一个 RabbitMQ 实例内独立运行,并增强安全性和可管理性。
在要求高容错性和消息可靠性的场景中,消息传递replicas
功能至关重要。这些用于仲裁队列的副本通过在多个节点或集群之间维护同步的消息副本来确保数据冗余和弹性。
消息传递模式🌐
发布/订阅
发布/订阅模式用于将消息广播给多个希望接收通知更新的订阅者。在此模式下,消息不是发布到单个队列,而是由交换机处理,然后交换机根据预先设定的路由规则和绑定将消息路由到多个队列。每个队列都通过路由键绑定到交换机。
工作队列
工作队列是一种在多个工作器或消费者之间分配和并行处理任务或消息的方法。它比发布/订阅模式更简单,因为它没有额外的交换代理抽象。在此模式中,任务或消息被发布到单个队列。多个工作器从该队列消费消息,每个工作器独立处理任务。
哦,顺便说一下
如果您支持致力于让 Kubernetes 包管理更好地为每个人服务的开源项目,那么请考虑支持 Glasskube,在GitHub上给我们一个 Star 🙏
消息传递系统的好处👍
缩放
如有需要,可添加队列expand capacity
。甚至可以耦合多个代理节点来形成消息传递clusters
。
批处理
批处理是指将多条消息分组为单个批次或捆绑包,然后再通过网络传输。这可以对性能、效率和资源利用率产生积极影响。
架构解耦
应用程序可以独立开发和扩展,从而优化资源使用和互操作性。
可靠性和持久性
根据clustering
、replicating
和node federation
,没有任何节点或存储卷完全负责数据持久化。任何节点都不需要成为单点故障。
用例
那么,哪些架构或应用可能从消息传递系统中受益最多呢?想想那些需要异步通信、可扩展性、可靠性以及组件间解耦的应用。社交媒体应用、金融服务、物联网产品、电信应用和供应链管理工具等解决方案只是其中几个例子。
消息应用程序示例: 💬
例如,每次您在 WhatsApp 或通过文本收到消息时,都会使用队列异步处理消息有效负载。
金融应用示例: 📈
当你使用金融应用程序下单购买你心仪的股票时,情况也是如此。购买详情将从生产者应用程序的前端传送到队列,以便后端消费者应用程序可以接收并继续处理你的购买订单。
+-------------+
| Financial |
| App |
+------+------+ +-----------------+
| | |
v | RabbitMQ |
+-----------+-----------+ | Broker |
| | | |
| User Initiates Buy +--------->+ Queue |
| Order | | |
| | +-----------------+
+-----------+-----------+ |
| |
v |
+-------------+ |
| Consumer | |
| App |<------------------------+
+-------------+
RabbitMQ 的功能
易于使用
与其他消息系统相比,RabbitMQ 的配置和使用简单性脱颖而出。
发货确认和消费者确认
消息成功消费后,系统会发出一个确认消息,这是同步通信的典型特征,但在异步通信中却不太常见。RabbitMQ 有一个功能可以实现这一点。
分布式网络
RabbitMQ 作为消息传递代理适合分布式架构,使用从远程主机连接的生产者和消费者应用程序,这使得 RabbitMQ 代理也适合分布式,有三种方法可以实现这一点:集群,联合或铲子插件。
工具+插件
RabbitMQ 拥有一系列工具和插件,使管理和配置更加便捷。例如,管理插件提供了一个实用的 GUI,可以用来管理、监控任务,此外还有部署插件。以下是一些实用的插件
-
rabbitmq_management:用于管理控制台访问
-
rabbitmq_prometheus:以 Prometheus 兼容格式导出指标,方便监控和观察。
-
rabbitmq_federation:支持集群和交换形成以及数据复制
-
rabbitmq_peer_discovery_k8s:用于 k8s 环境中的自动节点发现(集群形成)
-
RabbitMQ 自带一些实用的 CLI 工具
rabbitmqcli
,rabbitmq-plugins
和。它们在 RabbitMQ 节点内部执行rabbitmqadmin
,rabbitmq-queues
支持集群管理、插件配置以及一系列自定义功能。
RabbitMQ 安装方法
Docker🐳
# latest RabbitMQ 3.13
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.13-management
ℹ️ 查看Marcel Dempers 提供的关于 Docker 的深入安装指南
多种操作系统上的开源 RabbitMQ 服务器
RabbitMQ 集群 Kubernetes 操作员☸️
我们将重点介绍这种安装方法,因为它是在 Kubernetes 环境中使用 RabbitMQ 的推荐方法。
安装 RabbitMQ Cluster Kubernetes Operator
RabbitMQ Cluster Kubernetes Operator 可自动执行在 Kubernetes 上运行的 RabbitMQ 集群的配置、管理和操作。
安装
使用 Glasskube 包管理器可以轻松安装 RabbitMQ 集群操作员。
安装 Glasskube
如果您已经安装,glasskube
可以跳过此步骤。
如果没有,glasskube
您可以按照您通常为操作系统安装软件包的方式轻松安装。
MacOs:
brew install glasskube/tap/glasskube
Linux(Ubuntu/Debian)
curl -LO https://releases.dl.glasskube.dev/glasskube_v0.4.0_amd64.deb
sudo dpkg -i glasskube_v0.4.0_amd64.deb
更多安装指南请点击此处
安装 RabbitMQ 集群操作员
通过命令行启动 UI:
glasskube serve
通过 Glasskube UI 安装 RabbitMQ 集群操作员。
只需一个简单的命令即可安装包。
glasskube install rabbitmq-operator
该过程将等待直到包成功安装。
您需要访问正在运行或更高版本的 Kubernetes 集群(您可以使用MinikubeKubernetes 1.19
轻松创建本地集群)。严格来说,通过 Glasskube 安装软件包并非依赖项,但这是与集群交互的推荐方式。因此,我们强烈建议您这样做。安装说明适用于 macOS、Linux 和 Windows。kubectl
Glasskube 将自动在新创建的命名空间中安装集群操作员
rabbitmq-system
确认服务可用性
在配置您的应用程序以使用 RabbitMQ Cluster Kubernetes Operator 之前,请确保RabbitmqCluster
自定义资源已部署到您的 Kubernetes 集群并且可用。
要确认此可用性,请运行
kubectl get customresourcedefinitions.apiextensions.k8s.io
创建 RabbitMQ 实例
RabbitMQ Cluster Kubernetes Operator 在定义的同一命名空间中创建必要的资源,例如Services
、StatefulSets
和。Secrets
ConfigMaps
RabbitmqCluster
首先,创建一个 YAML 文件来定义一个RabbitmqCluster
名为 definition.yaml 的资源。
ℹ️注意: YAML 文件可以有任何名称,但以下步骤假定它被称为
definition.yaml
。
然后将以下代码片段复制并粘贴到文件中并保存:
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: definition
接下来,通过运行以下命令应用定义:
kubectl apply -f definition.yaml
然后通过运行以下命令验证该过程是否成功:
kubectl get all -l app.kubernetes.io/name=definition
配置 RabbitMQ 实例
要配置 RabbitMQ 实例(即集群本身),请打开 definition.yaml 或通过运行以下命令编辑配置:
kubectl edit rabbitmqcluster definition
默认情况下,支持 RabbitMQ 所需的所有清单和对象都已创建,要编辑它们,您只需编辑 Kubernetes 清单文件。
访问 Kubernetes 上的 RabbitMQ 仪表板
您可以通过多种方式访问 RabbitMQ 管理仪表板,但需要编辑服务对象并使用负载均衡器。最快捷且无需更改任何默认配置的方法是使用definition-server-0
Pod 端口转发。
kubectl port-forward -n rabbitmq-system definition-server-0 8080:15672
然后,您可以访问仪表板登录页面来访问控制台。要找到访问部署的凭据,您必须解码预配的 Kubernetes 密钥中的用户名和密码。
kubectl get secret definition-default-user -n rabbitmq-system -o yaml
输出将会是这样的:
apiVersion: v1
data:
default_user.conf: ZGVmYXVsdF91c2VYXVsdF91c2VyXzhMZklqOGFFQmROZmcKZGVmYXVsdF9wYXNzID0gd3IyWTl3MVJLMUtOdWN2S2ptS0FaX2R3dlRDSEhiYWEK
host: ZGVmaW5pdGlvbi5yYWJiaXRtcS1zeXN0ZW0uc3Zj
password: d3IyWTl3MVJLMUtOdWN2S2ptR3dlRDSEhiYWE=
port: NTYMg==
provider: cmFiml0bXE=
type: cmFiYmlbXE=
username: ZGVmYXVsdF91c2VMZklqFFQmRsbHd4b1BOZmc=
解码 base64password
和username
值并将输出传递到登录页面
# Password
➜ ~ echo -n d3IyWTl3MVJLMUtOdW2S2ptS0FaX2R3dlRDSEhiYWE= | base64 --decode
wr2Y9w1RK1KNucvKjmKAZ_dwvTCHHba%
# Username
➜ ~ echo -n ZGVmYXVsdF91c2VyXhMZklqOGFFQmRsbHd4b1BOZmc= | base64 --decode
default_user_8LfIj8aEBdllwxoPNf%
ℹ️ 要监控您的 RabbitMQ 实例,请查看此文档。
创建队列🚃
有多种方法可以在 RabbitMQ 中声明队列,具体取决于您的工作流程和偏好。
选项 1:在生产者应用中声明队列
大多数情况下,您会在使用您首选编程语言编写的生产者应用中声明一个队列。当应用发布第一条消息时,如果队列尚不存在,队列声明将自动创建该队列。此方法允许根据需要动态创建队列。
选项 2:RabbitMQ 配置文件
或者,您可以使用 RabbitMQ配置文件来声明多种类型的 RabbitMQ 对象,包括vhosts、channel、exchange和queues。此方法提供了一种更结构化的方式来管理 RabbitMQ 资源和配置。
选项 3:管理 UI
对于手动管理,您可以直接从 RabbitMQ 管理 UI 创建队列。它提供了一个用户友好的界面用于与 RabbitMQ 交互,让您无需使用命令行即可执行管理任务。
用户和虚拟主机创建(可选)
在创建队列之前,建议设置用户和虚拟主机,以便有效地组织消息传递工作流。例如:
rabbitmqctl add_user jake jakepassword
rabbitmqctl set_user_tags jake administrator
rabbitmqctl set_permissions -p / jake ".*" ".*" ".*"
rabbitmqctl add_vhost vhost-1
rabbitmqctl set_permissions -p vhost-1 jake ".*" ".*" ".*"
通过管理 UI 创建队列
-
访问 RabbitMQ 管理控制台:在您的 Web 浏览器中打开 RabbitMQ 管理 UI。
-
使用凭证登录:使用您创建的用户的凭证(例如,用户名:jake,密码:jakepassword)登录管理 UI。
-
导航到队列部分:单击管理 UI 中的“队列”选项卡以查看现有队列。
-
添加队列:滚动到页面底部,然后单击“添加新队列”按钮以创建新队列。
-
指定队列名称、类型和其他所需属性,如节点首选项。
-
或者,根据您的要求配置队列绑定、策略和其他高级设置。
- 保存更改:单击“添加队列”或“保存”按钮确认并创建新队列。
通过遵循这些步骤,您可以根据您的特定需求轻松地在 RabbitMQ 中创建和管理队列。
队列现已准备就绪:
构建 RabbitMQ 集群
在构建包含消息传递组件的生产应用程序时,必须考虑高可用性。RabbitMQ 提供了集群功能,该功能包括连接多个 RabbitMQ 代理并复制配置以及消息队列中包含的数据。
ℹ️ 要理解集群是如何形成的,我们需要了解一些概念。
使用 Operator 时,我们下面探讨的大部分概念都会默认配置。尽管如此,了解其底层机制仍然很有价值。
验证
一个 RabbitMQ 节点要与另一个需要共享 Erlang Cookie 环境变量的节点组成集群,需要共享相同的配置数据。这将确保节点共享所需的配置数据,从而将自身视为一个集群。但这并不能确保队列数据的复制。这就是镜像的概念的由来。
仲裁队列
RabbitMQ 仲裁队列是一种现代队列类型,它基于Raft 共识算法实现了持久的、可复制的 FIFO 队列。之前推荐使用经典镜像队列,但后来已被弃用。仲裁队列的实现方式大致相同,但它们通过复制提供高可用性,并注重数据安全。您可以将策略应用于队列,并通过这些策略来配置镜像规范。
队列声明
过去,队列的复制是通过结合使用策略和经典队列来指定的。仲裁队列的创建方式有所不同,但应该与所有允许在声明队列时提供参数的客户端应用程序兼容。创建队列时,需要为 x-queue-type 参数提供值 quorum。例如,使用 Elixir AMQP client1,声明仲裁队列的方法如下:
Queue.declare(publisher_chan, "my-quorum-queue", durable: true, arguments: [ "x-queue-type": "quorum" ])
ℹ️ 使用
rabbitmq-queues
CLI 轻松管理仲裁队列。以下是一些有用的 CLI命令。
自动故障转移
每个仲裁队列由一个主副本(在Raftleader
术语中称为)以及可能的多个辅助副本(称为)组成。followers
最初,在集群形成时会选出一个领导者,随后,如果当前领导者不可用,则会选出一个领导者。
假设某个仲裁队列的领导者节点因任何原因发生故障或停止运行。在这种情况下,另一个托管该仲裁队列的追随者节点将承担领导角色并恢复运行。
当故障或重新加入的跟随者恢复在线时,它们会经历一个与领导者重新同步的过程,通常称为“追赶”。与传统的镜像队列不同,在传统的镜像队列中,临时副本故障需要与当前领导者进行完全重新同步;而如果重新加入的副本落后于领导者,则只会传输差异更改。
容错
为了在 RabbitMQ 集群中获得最佳性能,将仲裁队列大小限制为较小的odd number
节点数是有益的。
还值得一提的是,当仲裁队列节点大小超过 5 时,性能往往会明显下降。因此,强烈建议不要在超过 7 个 RabbitMQ 节点上部署仲裁队列。
将实例添加到集群🪴
ℹ️ 部署后,集群操作员会自动生成一组 Kubernetes 清单文件,定义 RabbitMQ 实例的默认配置。您可以使用以下命令检查这些配置:Run
k get all -n rabbitmq-admin
以查看所有已创建的对象。您可以自定义和更新这些默认配置,以更好地满足您的特定需求和偏好。
RabbitMQ Kubernetes Operator 通过自动处理镜像、故障转移和节点联合等基本任务,简化了设置过程。这意味着创建 RabbitMQ 集群就像在RabbitmqCluster
定义文件中调整副本数量一样简单。借助这些内置功能,管理 RabbitMQ 集群变得更加无缝便捷。
在这里我更新了RabbitmqCluster
清单以扩展到3
副本:
RabbitmqCluster
ℹ️ 指定对象的副本数时,强烈建议不要使用偶数。必须使用奇数(1、3、5、7 等)。
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rabbitmq.com/v1beta1","kind":"RabbitmqCluster","metadata":{"annotations":{},"name":"definition","namespace":"rabbitmq-system"}}
creationTimestamp: "2024-05-07T17:04:53Z"
finalizers:
- deletion.finalizers.rabbitmqclusters.rabbitmq.com
generation: 6
name: definition
namespace: rabbitmq-system
resourceVersion: "2729957"
uid: f9b4cad8-68b4-489e-b7a1-baa3b91882d5
spec:
delayStartSeconds: 30
image: rabbitmq:3.13.1-management
override: {}
persistence:
storage: 10Gi
rabbitmq:
additionalConfig: |
load_definitions = /etc/rabbitmq/definitions.json
replicas: 3 # added three replicas which will for the RabbitMQ cluster
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: "1"
memory: 2Gi
secretBackend:
externalSecret: {}
service:
type: ClusterIP
terminationGracePeriodSeconds: 604800
...
不仅节点已添加到集群,而且队列也已自动复制到所有集群节点
诸如 RabbitMQ 之类的消息代理在事件驱动架构中扮演着核心角色,它提供flexibility
、task processing
和workflow orchestration
,service integrations
同时提供多种选择,以最适合您的架构。在优先考虑和时,由于其原生的确认和消息持久化功能,messaging patterns
它是显而易见的选择。delivery reliability
fault tolerance
现在,RabbitMQ 的入门比以往任何时候都更加简单,尤其是在Glasskube集成了集群控制器,方便安装和管理的情况下。本指南旨在提供在 Kubernetes 环境中搭建功能实例或 RabbitMQ 集群所需的必要信息。虽然关于 RabbitMQ 还有很多其他内容需要学习,但我希望本入门指南能为您的 RabbitMQ 之旅提供充足的基础。
如果您喜欢这类内容并希望看到更多,请考虑在 GitHub 上给我们一个 Star 来支持我们🙏
鏂囩珷鏉ユ簮锛�https://dev.to/glasskube/rabbitmq-on-kubernetes-1pi2