RabbitMQ 教程译文(三) + 学习

2024-05-01 00:58
文章标签 学习 教程 rabbitmq 译文

本文主要是介绍RabbitMQ 教程译文(三) + 学习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址
除了特殊声明,以下所有图片皆来自教程原文

发布订阅
在之前的教程中,我们创建了一个工作队列。在例子中我们假设,每一个任务会发送给特定的一个消费者。在本章节中,我们要做完全不同的事:我们将会发送信息给多个消费者,这就是发布订阅模式。

为了描述这个模式,我们将会创建一个简单的日志系统。这个系统包含两部分内容,一是发出日志信息,二是接收并打印日志信息。

在我们的系统中,每一个运行的接收日志的程序都会接收到日志信息。这种情况下我们可能使用一个接收者将日志直接存储到硬盘,使用另一个接收者用于屏幕展示。

总的来说,日志信息将会广播给所有的接收者。

Exchanges
在之前的教程中,我们通过一个队列来发送和接收信息。现在是时候介绍Rabbit中的完整信息模型了
我们先快速回忆下之前的教程内容
1、生产者就是一个发送信息的用户应用
2、队列就是存储信息的缓存
3、消费者就是一个接收信息的用户应用

在RabbitMQ中,消息模型的核心思想就是:生产者不会直接给队列发送信息。甚至大部分情况是生产者根本不知道队列的存在。

生产者只可以发送信息到一个exchangeexchange其实很简单,一方面接收生产者发送的信息,一方面把信息加入到队列中。exchange必须知道怎么处理它接收到的信息。是要把它发送到指定队列么?还是发送到很多队列?或者是不是应该丢弃。这些处理规则通过exchange类型来定义。
在这里插入图片描述
下面是一些有效的exchange类型:directtopicheadersfanout。我们重点看下最后一个类型,fanout。现在我们来创建这个类型的exchange,我们叫它“logs”。

channel.exchangeDeclare("logs", "fanout");

fanout类型的exchange非常简单,你可能已经根据名称猜出它的用途了,该类型的exchange会广播所有它接收到的信息给它知道的所有队列。这正是我们日志系统需要的。

展示Exchanges
你可以通过rabbitmqctl命令在服务端展示所有的exchange

sudo rabbitmqctl list_exchanges

在这个列表中,可能会有很多“amq.”的exchange和一些默认的exchange*,这些都是默认创建的exchange,目前你还不会用到。

未命名的exchange
在之前的教程中,我们一点都不知道exchange的存在,但是我们还是向队列发送了信息。这是因为我们之前使用了默认的exchange,我们是通过空字符串来定义的exchange。回忆下我们之前是怎么发送信息的

channel.basicPublish("", "hello", null, message.getBytes());

这个方法的第一个参数就是exchange的名称。空字符串表示这是一个默认或者无名的exchange。如果“routingKey”存在的话,信息会通过该值发送到指定队列。

现在我们使用一个命名的exchange替换之前的

channel.basicPublish( "logs", "", null, message.getBytes());

Temporary Queue临时队列
在我们之前的教程中,我们都会给队列一个名称(“hello”、“task_queue”)。对于我们来说给一个队列命名是非常重要的,这样我们就可以指定消费者消费哪个队列。所以当你需要在生产者和消费者见共享队列信息,给队列命名是非常重要的。

但是,这些对我们日志来说是不重要的。我们想获取所有的日志信息,而不是它的一部分。我们对于新的日志感兴趣而不是旧的日志。为了解决这个问题,我们需要做两件事。

首先,无论何时我们连接到Rabbit,我们需要一个全新的空的队列。为了实现这个我们需要创建一个有随机名称的队列,或者更好的情况是服务器给我们队列一个随机名称。

其次,当消费者断开连接,队列要自动删除。

在java实现中,我们提供了一个无参方法queueDeclare(),该方法会创建一个非持久,专一的(exclusive),自动删除的队列,该队列的名称是服务端生成的。

String queueName = channel.queueDeclare().getQueue();

你可以在文档中学习更多关于exclusive标识和其他参数的知识。

在上述代码中,“queueName” 是一个随机生成的名称,它可能像这样“amq.gen-JzTY20BRgKO-HjmUJj0wLg”。

Bindings绑定
在这里插入图片描述
我们已经创建了一个fanout类型的exchange和一个队列,现在我们要让exchange发送信息到队列中。exchange和队列中间的关系我们叫做绑定(Binding)。

channel.queueBind(queueName, "logs", "");

从现在开始,“logs”exchange将会发送信息到队列中。

Putting it all together 合体~
在这里插入图片描述
发送信息的生产者程序和之前教程中的看起来没什么不一样。最大的改变就是,现在我们发送信息到“logs”exchange,而不是之前的无名exchange。在发送过程中我们需要提供routingKey,但是它对于fanout类型的exchange是无效的。下面就是全部的生产者程序“EmitLog.java”

public class EmitLog {private static final String EXCHANGE_NAME = "logs";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection();Channel channel = connection.createChannel()) {channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String message = argv.length < 1 ? "info: Hello World!" :String.join(" ", argv);channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));System.out.println(" [x] Sent '" + message + "'");}}
}

正如你所见,我们在创建连接之后声明了一个exchange,这一步很有必要,它避免了发送信息到一个不存在的exchange中。

如果没有队列绑定到exchange,那么exchange中的信息将会丢失,但是这些对我们日志系统没什么影响;如果还没有消费者监听队列,那我们可以安全的丢弃这些信息。

“ReceiveLog.java”的代码

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;public class ReceiveLogs {private static final String EXCHANGE_NAME = "logs";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String queueName = channel.queueDeclare().getQueue();channel.queueBind(queueName, EXCHANGE_NAME, "");System.out.println(" [*] Waiting for messages. To exit press CTRL+C");DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");};channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });}
}

后面就是运行查看结果

打完收工~~

这篇关于RabbitMQ 教程译文(三) + 学习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950352

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

RabbitMQ 延时队列插件安装与使用示例详解(基于 Delayed Message Plugin)

《RabbitMQ延时队列插件安装与使用示例详解(基于DelayedMessagePlugin)》本文详解RabbitMQ通过安装rabbitmq_delayed_message_exchan... 目录 一、什么是 RabbitMQ 延时队列? 二、安装前准备✅ RabbitMQ 环境要求 三、安装延时队

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

spring AMQP代码生成rabbitmq的exchange and queue教程

《springAMQP代码生成rabbitmq的exchangeandqueue教程》使用SpringAMQP代码直接创建RabbitMQexchange和queue,并确保绑定关系自动成立,简... 目录spring AMQP代码生成rabbitmq的exchange and 编程queue执行结果总结s

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地