RabbitMQ入门实战
RabbitMQ 是一个开源的消息中间件,实现了高级消息队列协议(AMQP),用于在分布式系统中进行消息传递。它能够在应用之间传递消息,解耦应用组件,提高系统的可伸缩性和可维护性。RabbitMQ 使用高级消息队列协议(AMQP),这是一种开放的、标准化的协议,定义了消息格式、交换方式、队列管理等规范。拥有强大的社区支持,提供了广泛的文档和示例。它还支持插件机制,可以根据实际需求进行扩展。下面就对rabbitMQ进行实战。
官网:RabbitMQ: easy to use, flexible messaging and streaming — RabbitMQ
1. 基本概念
- 消息队列:消息队列是一种在不同应用之间传递数据的机制。在RabbitMQ中,消息队列是通过Exchange(交换机)来进行消息路由的。
- Exchange:Exchange负责将消息路由到一个或多个队列。RabbitMQ支持不同类型的Exchange,包括Direct、Fanout、Topic等。
- Queue:Queue是消息的容器,消息在发送到Exchange后通过Routing Key被路由到一个或多个Queue中。
2. 使用场景
消息中间件经常被用来处理异步、削峰填谷,和多个组件之间进行解耦的作用。
- 异步任务处理:RabbitMQ可以作为任务队列,将任务发布到队列中,然后由后台工作者异步处理。这在分布式系统中很常见,可以提高系统的响应速度。
- 事件驱动架构:RabbitMQ可以用于实现事件驱动的架构,不同组件之间通过消息进行通信。当某个事件发生时,可以将消息发送到队列中,由其他组件进行消费。
- 日志收集:RabbitMQ可以用于日志收集系统,应用程序将日志消息发送到队列中,日志收集器订阅队列并将日志保存到数据库或其他存储中。
3. RabbitMQ实战
3.1 rabbitMQ安装
这里演示使用docker-compose方式安装,创建一个docker-compose.yml文件并写入以下内容
version: '3'services:rabbitmq:image: "rabbitmq:management"container_name: "rabbitmq-container"ports:- "5672:5672" # RabbitMQ 默认端口- "15672:15672" # RabbitMQ 管理界面端口volumes:- "./rabbitmq-data:/var/lib/rabbitmq" # 数据文件挂载environment:RABBITMQ_DEFAULT_USER: "rabbit"RABBITMQ_DEFAULT_PASS: "rabbit1qz"
执行命令拉取并启动容器
docker-compose up -d
执行命令查看docker容器是否正常
docker ps | grep rabbit
然后地址栏http://localhost:15672/访问rabbitMQ管理界面
输入用户名密码可以看到如下界面,在这个页面上可以创建Exchanges和Queue,这里就不赘述了,大家想了解的可以参考官方文档。
3.1 代码集成
上面安装完MQ组件之后,就可以用java代码进行连接测试了。使用Maven添加RabbitMQ的Java客户端库到项目里:
<dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.14.0</version> <!-- 替换为最新版本 -->
</dependency>
3.2 发送消息
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Channel;public class MessageSender {private final static String QUEUE_NAME = "hello";public static void main(String[] argv) throws Exception {// 创建连接工厂ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost"); // RabbitMQ服务器地址// 创建连接try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 发送消息String message = "Hello, RabbitMQ!";channel.basicPublish("", QUEUE_NAME, null, message.getBytes());System.out.println(" [x] Sent '" + message + "'");}}
}
3.3 接收消息
import com.rabbitmq.client.*;public class MessageReceiver {private final static String QUEUE_NAME = "hello";public static void main(String[] argv) throws Exception {// 创建连接工厂ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost"); // RabbitMQ服务器地址// 创建连接try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 定义消息处理器DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");};// 监听队列,接收消息channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});// 持续监听队列,不会退出System.out.println(" [*] Waiting for messages. To exit press Ctrl+C");Thread.sleep(Long.MAX_VALUE);}}
}
以上示例中,MessageSender
类用于发送消息到名为"hello"的队列,而MessageReceiver
类用于监听该队列并接收消息。
4. RabbitMQ高级特性
RabbitMQ 提供了许多高级特性,包括持久化、消息确认、事务、死信队列等。下面将结合 Java 完整代码进行说明这些高级特性。
1. 持久化
持久化确保在 RabbitMQ 服务器重启时,队列和消息不会丢失。
代码示例
// 发布者代码
public class DurableProducer {// ...初始化 RabbitMQ 连接等代码...public void publishPersistentMessage(String message) {channel.basicPublish("", "durable_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());System.out.println(" [x] Sent '" + message + "'");}
}// 订阅者代码
public class DurableSubscriber {// ...初始化 RabbitMQ 连接等代码...public void subscribeToPersistentMessages() {channel.queueDeclare("durable_queue", true, false, false, null);channel.basicConsume("durable_queue", true, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");// 处理消息的逻辑...}, consumerTag -> {});}
}
2. 消息确认
消息确认确保消息已经被消费者成功处理。
代码示例
// 发布者代码
public class AckProducer {// ...初始化 RabbitMQ 连接等代码...public void publishAckMessage(String message) {channel.basicPublish("", "ack_queue", null, message.getBytes());System.out.println(" [x] Sent '" + message + "'");}
}// 订阅者代码
public class AckSubscriber {// ...初始化 RabbitMQ 连接等代码...public void subscribeToAckMessages() {channel.queueDeclare("ack_queue", false, false, false, null);channel.basicConsume("ack_queue", false, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");// 处理消息的逻辑...// 手动发送消息确认channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);}, consumerTag -> {});}
}
3. 事务
RabbitMQ 支持事务,但由于性能问题,通常建议使用消息确认代替。
代码示例
// 发布者代码
public class TransactionalProducer {// ...初始化 RabbitMQ 连接等代码...public void publishTransactionalMessage(String message) throws IOException {try {channel.txSelect(); // 开启事务channel.basicPublish("", "transactional_queue", null, message.getBytes());System.out.println(" [x] Sent '" + message + "'");channel.txCommit(); // 提交事务} catch (IOException e) {channel.txRollback(); // 回滚事务e.printStackTrace();}}
}// 订阅者代码
public class TransactionalSubscriber {// ...初始化 RabbitMQ 连接等代码...public void subscribeToTransactionalMessages() {try {channel.queueDeclare("transactional_queue", false, false, false, null);while (true) {channel.txSelect(); // 开启事务GetResponse response = channel.basicGet("transactional_queue", true);if (response != null) {String message = new String(response.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");// 处理消息的逻辑...channel.txCommit(); // 提交事务} else {channel.txRollback(); // 回滚事务}}} catch (IOException e) {e.printStackTrace();}}
}
4. 死信队列
死信队列用于处理无法被消费者成功处理的消息。
代码示例
// 发布者代码
public class DeadLetterProducer {// ...初始化 RabbitMQ 连接等代码...public void publishDeadLetterMessage(String message) {Map<String, Object> headers = new HashMap<>();headers.put("x-dead-letter-exchange", "dead_letter_exchange");headers.put("x-dead-letter-routing-key", "dl_queue");AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder().headers(headers).build();channel.basicPublish("", "original_queue", properties, message.getBytes());System.out.println(" [x] Sent '" + message + "'");}
}// 订阅者代码
public class DeadLetterSubscriber {// ...初始化 RabbitMQ 连接等代码...public void subscribeToDeadLetterMessages() {channel.exchangeDeclare("dead_letter_exchange", BuiltinExchangeType.DIRECT);channel.queueDeclare("dl_queue", false, false, false, null);channel.queueBind("dl_queue", "dead_letter_exchange", "");channel.queueDeclare("original_queue", false, false, false, null);channel.queueBind("original_queue", "", "original_queue");channel.basicConsume("original_queue", false, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");// 处理消息的逻辑...// 模拟处理失败,将消息发送到死信队列channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, false);}, consumerTag -> {});}
}
这些是 RabbitMQ 的一些高级特性的简单示例。在实际项目中,具体的实现可能会更加复杂,并需要根据场景进行适当的调整。
5. 总结
RabbitMQ作为一款强大的消息中间件,在异步任务处理、事件驱动架构以及日志收集等场景中都有广泛的应用。通过简单的代码实例,我们了解了RabbitMQ的基本概念以及如何在Java中使用RabbitMQ进行消息的发送和接收。
希望本文能够帮助大家入门RabbitMQ,并在实际项目中灵活应用消息队列的机制。
相关文章:

RabbitMQ入门实战
RabbitMQ 是一个开源的消息中间件,实现了高级消息队列协议(AMQP),用于在分布式系统中进行消息传递。它能够在应用之间传递消息,解耦应用组件,提高系统的可伸缩性和可维护性。RabbitMQ 使用高级消息队列协议…...

vue3-模版引用ref
1. 介绍 概念:通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤: 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下: 父组件: <script setup> import { onMounted, ref } …...
C# 十大排序算法
以下是常见的十大排序算法(按照学习和实现的顺序排列): 冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort)希尔排序(Shell Sort&…...

面试之Glide如何绑定Activity的生命周期
Glide绑定Activity生命周期 Glide.with() 下面都是它的重载方法,Context,Activity,FragmentActivity, Fragment, android.app.Fragment fragment,View都可以作为他的参数,内容大同小异,都是先getRetriever࿰…...

从 fatal 错误到 sync.Map:Go中 Map 的并发策略
为什么 Go 语言在多个 goroutine 同时访问和修改同一个 map 时,会报出 fatal 错误而不是 panic?我们该如何应对 map 的数据竞争问题呢? 这篇文章将带你一步步了解背后的原理,并引出解决 map 并发问题的方案。 Map 数据竞争 首先…...
Simon算法详解
0.0 Intro 相关的算法: Deutsh-Jozsa算法: 第一个量子算法对经典算法取得指数级加速的算法 美中不足在于只能确定函数是平衡的还是非平衡的,无法确定函数具体的内容,即无法直接解出函数 Bernstein-Vazirani算法ÿ…...

jrebel IDEA 热部署
1 下载 2022.4.1 JRebel and XRebel - IntelliJ IDEs Plugin | Marketplace 2 选择下载好的zip 离线安装IDEA 插件 重启IDEA 3 打开 [Preference -> JRebel & XRebel] 菜单,输入 GUID address 为 https://jrebel.qekang.com/1e67ec1b-122f-4708-87d…...
pdf拆分成各个小pdf的方法
背景:由于某些缘故,一个大的pdf需要拆分成页数少的pdf,或者pdf需要去掉指定页,那么就有必要对pdf进行重新编辑,这里需要用到一个库,直接进行操作即可。 当使用Python时,可以使用PyMuPDF库来拆分PDF文件。以下是一个示例代码, import fitz # PyMuPDF def split_pdf(i…...

IntelliJ IDEA 常用快捷键一览表(通用型,提高编写速度,类结构、查找和查看源码,替换与关闭,调整格式)
文章目录 IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组:通用型第2组:提高编写速度(上)第3组:提高编写速度(下)第4组:类结构、查找和查看源码第5组:查找、替换…...

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:
前言: 本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。 本文缩语: MT = Matlab 问题提出: 1 我们有一个比较复杂的Matlab文件: 这个MATLAB的算法,写了很多的算法函数在其他的M文件里面,这样,前面博客的方法就不够用了。会报错: 解决办法如下…...

上位机图像处理和嵌入式模块部署(qt图像处理)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 很多人一想到图像处理,本能的第一反应就是opencv,这也没有错。但是呢,这里面还是有一个问题的,不知…...

AI教我学编程之C#类的实例化与访问修饰符
前言 在这篇文章中,我将带大家深入了解C#编程语言的核心概念,包括类的实例化、访问修饰符的应用,以及C#中不同数据类型的默认值。我会通过逐步分析和具体实例,详细解释如何在C#中正确创建和操作对象,并探讨如何通过访…...

【笔记】Blender4.0建模入门-3物体的基本操作
Blender入门 ——邵发 3.1 物体的移动 演示: 1、选中一个物体 2、选中移动工具 3、移动 - 沿坐标轴移动 - 在坐标平面内移动 - 自由移动(不好控制) 选中物体:右上的大纲窗口,点击物体名称,物体的轮…...

一文详解 Berachain 测试网:全面介绍与教程,bitget wallet教程
什么是Berachain? Berachain(web3.bitget.com/zh-CN/assets/berachain-wallet)是一种尖端区块链技术,使用 Cosmos SDK 构建的 Layer-1,兼容以太坊虚拟机(EVM)。它基于一种独特的概念,…...

小程序使用echarts图表-雷达图
本文介绍下小程序中如何使用echarts 如果是通过npm安装,这样是全部安装的,体积有点大 我这边是使用echarts中的一个组件来实现的,下边是具体流程,实际效果是没有外边的红色边框的,加红色边框的效果是这篇说明 1.echa…...

MacM1Pro Parallels19.1.0 CentOS7.9 Install PostgrepSQL
相关阅读 MacM1Pro安装 Parallels Desktop 19.1.0 https://blog.csdn.net/qq_41594280/article/details/135420241 MacM1Pro Parallels安装Parallels Tools https://blog.csdn.net/qq_41594280/article/details/135398780 MacM1Pro Parallels安装CentOS7.9 https://blog.csdn.n…...

Golang 中如何实现 Set
在Go编程中,数据结构的选择对解决问题至关重要。本文将探讨如何在 GO 中实现 set 和 bitset 两种数据结构,以及它们在Go中的应用场景。 Go 的数据结构 Go 内置的数据结构并不多。工作中,我们最常用的两种数据结构分别是 slice 和 map&#…...

记录一下uniapp 集成腾讯im特别卡(已解决)
uniapp的项目运行在微信小程序 , 安卓 , ios手机三端 , 之前这个项目集成过im,不过版本太老了,0.x的版本, 现在需要添加客服功能,所以就升级了 由于是二开 , 也为了方便 , 沿用之前的webview嵌套腾讯IM的方案 , 选用uniapp集成ui ,升级之后所有安卓用户反馈点击进去特别卡,几…...
React16源码: React中的updateHostRoot的源码实现
HostRoot 的更新 1 )概述 HostRoot 是一个比较特殊的节点, 因为在一个react应用当中它只会有一个 HostRoot, 它对应的 Fiber 对象是我们的 RootFiber 对象重点在于它的更新过程 2 )源码 定位到 packages/react-reconciler/src/ReactFiberBeginWork.js…...
Template -- React
React 版本 Node 21.6.0Npm 10.2.4 项目 创建 npm init vite 项目名称reactjsnpm inpm run dev 依赖 npm i axios # 网络 npm i antd --save # UI npm i ant-design/icons npm i react-router-dom # 路由npm i sass -D # …...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...

RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...

【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项
一、条形码识别改名使用教程 打开软件并选择处理模式:打开软件后,根据要处理的文件类型,选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件,就选择 “PDF 识别模式”;若是处理图片文件&…...