Go实现RabbitMQ消息模式

【目标】

  1. go实现RabbitMQ简单模式和work工作模式

  2. go实现RabbitMQ 消息持久化和手动应答

  3. go实现RabbitMQ 发布订阅模式

  4. go使用MQ实现评论后排行榜更新

1. go实现简单模式

编写路由实现生产消息

实现生产消息

MQ消息执行为命令行执行,所以创建命令行执行函数main,用来消费消息

创建mq/demo/main.go

浏览器中访问路由,执行生产者生产消息

打开http://localhost:15672/#/queues, 查看RabbitMQ客户端查看是否消息

执行消费者,实现消息消费

进入 mq/demo/中,执行bee run

2. go实现work工作模式

在启动另一个窗口,实现第二个消费者

生产消息

打开RabbitMQ客户端,查看消费者

查看work消费

两个work时,轮询执行消费

2.1 go实现RabbitMQ消息持久化和手动应答

消息持久化

消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保证消息可靠性的呢——消息持久化。
为了保证RabbitMQ在退出或者crash等异常情况下数据没有丢失,需要将queue,exchange和Message都持久化

生产者实现消息持久化

第二个参数设置为true,即durable=true.

消费者实现消息持久化

在RabbitMQ服务重启或者服务宕机的情况下,也不会丢失消息。

可以将Queue与Message都设置为可持久化(durable),这样可以保证绝大部分情况下RabbitMQ消息不会丢失。

手动应答

RabbitMQ 消息应答机制

消费者处理一个任务是需要一段时间的,如果有一个消费者正在处理一个比较耗时的任务并且只处理了一部分,突然这个时候消费者宕机了,那么会出现什么情况呢?

如果是自动应答模式,消费者在处理任务的过程中宕机了,那么消息将会丢失,而手动应答则能够保证消息不会被丢失,所以在实际的应用当中绝大多数都采用手动应答

为了保证消息从队列可靠地达到消费者并且被消费者消费处理,RabbitMQ 提供了消息应答机制,RabbitMQ 有两种应答机制,自动应答和手动应答

1、自动应答

RabbitMQ 只要将消息分发给消费者就被认为消息传递成功,就会将内存中的消息删除,而不管消费者有没有处理完消息

2、手动应答

RabbitMQ 将消息分发给了消费者,并且只有当消费者处理完成了整个消息之后才会被认为消息传递成功了,然后才会将内存中的消息删除

消息应答:

消费者在接收到消息并且处理该消息之后,告诉 rabbitmq 它已经处理了,rabbitmq 可以把该消息删除了

手动应答优点:

可以批量应答并且减少网络拥堵

消费方法中设置手动应答

效果:

关闭自动应答

RabbitMQ中查看

开启手动应答后,才返回消息执行成功,保证了消息不会被丢失

3. go实现RabbitMQ 发布订阅模式

RabbitMq消息模式的核心思想是:

一个生产者并不会直接往一个队列中发送消息,事实上,生产者根本不知道它发送的消息将被转发到哪些队列。

  实际上,生产者只能把消息发送给一个exchange(交换机),exchange只做一件简单的事情:一方面它们接收从生产者发送过来的消息,另一方面,它们把接收到的消息推送给队列。一个exchage必须清楚地知道如何处理一条消息。

有四种类型的交换器,分别是:direct、topic、headers、fanous(广播模式)

广播模式交换器很简单,从字面意思也能理解,它其实就是把接收到的消息推送给所有它知道的队列。在我们的日志系统中正好需要这种模式。

go实现RabbitMQ 发布订阅模式 RabbitMQ tutorial - Publish/Subscribe | RabbitMQ

实现广播模式(发布订阅模式)demo

生产者向交换机中发送消息

和简单模式、work模式相比,多了创建交换机

消费者拉取交换机中消息实现消费

和简单模式、work模式相比,多了创建交换机、创建了临时队列、绑定临时队列

临时队列

  我们使用的队列都是有具体的队列名,创建命名队列是很必要的,因为我们需要将消费者指向同一名字的队列。因此,要想在生产者和消费者中间共享队列就必须要使用命名队列。

 demo中的日志系统也可以使用非命名队列(可以不手动命名),我们希望收到所有日志消息,而不是部分。并且我们希望总是接收到新的日志消息而不是旧的日志消息。为了解决这个问题,需要分两步走。

  首先,无论何时我们的消费者连接到RabbitMq,我们都需要一个新的、空的队列来接收日志消息,因此,消费者在连接上RabbitMq之后需要创建一个任意名字的队列,或者让RabbitMq生成任意的队列名字。

  其次,一旦该消费者断开了与RabbitMq的连接,队列也被自动删除。

  通过queueDeclare()来创建一个非持久化、专有的、自动删除的、名字随机生成的队列。

实现发布订阅模式:

创建消息路由

控制器中实现生产者消息推送到交换机

创建mq/fanout/main.go,实现消费者从交换机中获取消息实现消费

效果:

执行生产者,实现消息生产

打开RabbitMQ客户端,查看消息状态

执行消费者,实现消费

注:因为是发布订阅模式。所以我们启动两个消费者实现多个用户消费同一消息

消费者1

消费者2

当生产者生产消息时,所订阅的消费者会执行消费

消费者1

消费者2

4. go实现RabbitMQ 路由模式


一个通过路由把One的消息取出来,另一个通过路由把two的消息取出来,一个队列打印奇数,一个队列打印偶数

生产者代码

消费者代码奇数代码


消费者代码偶数代码

运行效果

5. go实现RabbitMQ 主题模式


生产者代码

// topic主题push
// @router /mq/topic/push [*]
func (this *MqDemoController) GetTopic() {//创建线程执行(发送自增的数字到队列中)go func() {count := 0for {if count%2 == 0 {//strconv.Itoa 把count转化为字符串mq.PublishEx("wsyb.demo.topic", "topic", "wsyb.video", "wsyb.video"+strconv.Itoa(count))} else {mq.PublishEx("wsyb.demo.topic", "topic", "user.wsyb", "user.wsyb"+strconv.Itoa(count))}count++time.Sleep(1 * time.Second)}}()this.Ctx.WriteString("topic")
}// topic主题push
// @router /mq/topictwo/push [*]
func (this *MqDemoController) GetTopicTwo() {//创建线程执行(发送自增的数字到队列中)go func() {count := 0for {if count%2 == 0 {//strconv.Itoa 把count转化为字符串mq.PublishEx("wsyb.demo.topic", "topic", "a.frog.name", "a.frog.name"+strconv.Itoa(count))} else {mq.PublishEx("wsyb.demo.topic", "topic", "b.frog.uid", "b.frog.uid"+strconv.Itoa(count))}count++time.Sleep(1 * time.Second)}}()this.Ctx.WriteString("topic")
}

消费所有主题代码(#)

// 包名必须是main否则消费不成功
package mainimport ("fmt""wsybapi/services/mq"
)func main() {//执行消费  # 代表获取所有的数据mq.ConsumerEx("wsyb.demo.topic", "topic", "#", callback)
}// 回调函数
func callback(s string) {//打印消费结果fmt.Printf("topic all msg is :%s\n", s)
}

匹配多个规则进行消费

// 包名必须是main否则消费不成功
package mainimport ("fmt""wsybapi/services/mq"
)func main() {//执行消费 * 匹配一个或者多个符合规则的数据mq.ConsumerEx("wsyb.demo.topic", "topic", "*.frog.*", callback)
}// 回调函数
func callback(s string) {//打印消费结果fmt.Printf("topic frog msg is :%s\n", s)
}

匹配一个规则进行消费

// 包名必须是main否则消费不成功
package mainimport ("fmt""wsybapi/services/mq"
)func main() {//执行消费mq.ConsumerEx("wsyb.demo.topic", "topic", "wsyb.*", callback)
}// 回调函数
func callback(s string) {//打印消费结果fmt.Printf("tpic wsyb msg is :%s\n", s)
}

运行结果

6. rabbitmq死信队列

6.1应用场景:
  1. 发送消息规定10分钟以后发送给用户
  2. 规定消息每天固定的时间发送
    3.下了订单没有支付,30分钟以后就会取消订单
    4.订单相关的,下单以后会定时收到会系统的提示消息
6.2什么是死信队列呢:

死信队列产生的条件,不仅是ttl时间过期了,还有消息被拒绝,队列达到最大长度,都会产生死信,相信大家已经明白了

7. go使用MQ实现评论后排行榜更新

修改逻辑,新增评论时更新redis排行榜的数据

发布评论

打开MQ客户端,查看队列状态

创建mq/top/main.go,连接数据库

在消费回调函数中,编写消费者逻辑实现排行榜更新

执行消费者

效果:

先评论内容

打开redis可视化界面,查看排行榜评论数

再次评论

打开redis可视化界面,查看排行榜评论数是否实现更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/436360.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习-KNN分类算法

1.1 KNN分类 KNN分类算法(K-Nearest-Neighbors Classification),又叫K近邻算法。它是概念极其简单,而效果又很优秀的分类算法。1967年由Cover T和Hart P提出。 KNN分类算法的核心思想:如果一个样本在特征空间中的k个最…

聊一聊 C#中有趣的 SourceGenerator生成器

一:背景 1. 讲故事 前些天在看 AOT的时候关注了下 源生成器,挺有意思的一个东西,今天写一篇文章简单的分享下。 二:源生成器探究之旅 1. 源生成器是什么 简单来说,源生成器是Roslyn编译器给程序员开的一道口子&am…

【架构】NewSQL

文章目录 NewSQLTiDBTiDB 主要组件特点使用场景安装与部署 推荐阅读 NewSQL NewSQL是一种数据库管理系统(DBMS)的类别,它结合了NoSQL数据库的可扩展性和传统SQL数据库的事务一致性。具体来说,NewSQL数据库旨在解决传统关系型数据库在处理大规模并发事务…

我是如何将 Java 基础 docker 镜像大小从 674Mb 优化到 58Mb的

我是如何将 Java 基础 docker 镜像大小从 674Mb 优化到 58Mb的 如果您是 Java 开发人员,并且正在使用 Docker 打包应用程序,您可能已经注意到,即使是“hello world”类型的项目,最终镜像的大小也可能非常大。在本文中&#xff0c…

D18【python接口自动化学习】-python基础之内置数据类型

day18 综合练习:实现手机通讯录(下) 学习日期:20240925 学习目标:内置数据类型--27 小试牛刀:如何使用类型转换实现手机通讯录(下) 学习笔记: 实现手机通讯录 案例文…

【C语言】字符和字符串函数(2)

文章目录 一、strncpy函数的使用二、strncat函数的使用三、strncmp函数的使用四、strstr的使用和模拟实现五、strtok函数的使用六、strerr函数的使用 一、strncpy函数的使用 我们之前学习的strcpy的作用是把源字符串拷贝到目标空间内,而且经过我们的模拟实现&#x…

【Linux:线程概念】

目录 概念: 创建线程的函数:​编辑 ​编辑 有多进程为什么还需要有多线程? 线程调度的成本为什么低? 进程与线程的区别: 概念: 线程是CPU的基本调度单位,在进程内部运行。在内核中&#xff…

数据库系统

数据库管理系统 DBMS Database Management System分为三类: 关系数据库系统(Relation Database System) 面向对象数据库系统 (Object-Oriented Database System) 对象关系数据库系统 (Object-Oriented Relation Database System) 数据库设…

Stable Diffusion绘画 | SDXL模型使用注意事项

注意事项 SDXL模型的使用,对电脑配置要求更高,需要 8GB 以上显存的显卡SDXL模型兼容性不太好,容易出现错误,对 Mac 电脑不友好只能选择 SDXL模型 训练的 LoRA 使用不能使用旧的 VAE文件 SDXL 专用 VAE 文件:sdxl_vae.…

在矩池云使用 Llama-3.2-11B-Vision 详细指南

Llama 3.2-Vision是Meta开发的一系列多模态大型语言模型(LLMs),包含11B和90B两种规模的预训练和指令调整模型。 这些模型专门优化用于视觉识别、图像推理、字幕生成和回答有关图像的一般问题。Llama 3.2-Vision模型在常见行业基准测试中的表…

【网络安全】内部应用中的多重漏洞利用

未经许可,不得转载。 文章目录 初步发现:帐户枚举利用帐户枚举发现 IDOR 导致帐户接管拦截请求洪水攻击:注册拒绝服务目标网站:https://redacted.com 初步发现:帐户枚举 在最近的一次渗透测试中,我对一个仅供员工使用的内部应用程序进行了评估,重点关注身份验证和帐户…

HR告诉你:HCIE证书到底是职场神话还是锦上添花?真相大解析

在职场内卷的赛道上,每个人都在寻找能让自己脱颖而出的光环。而HCIE证书,作为IT领域的一项高含金量认证,莫过于优势最高最让人垂涎的光环,许多人相信它能开启通往理想职位的大门。 但在这个快速变化的时代,HCIE证书真的…

基于Hive和Hadoop的电商消费分析系统

本项目是一个基于大数据技术的电商消费分析系统,旨在为用户提供全面的电商消费信息和深入的消费行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理,利用 MapReduce 进行数据分析和处理,通过 Sqoop 实现数据的导入导出,以 S…

望繁信科技CTO李进峰受邀在上海外国语大学开展流程挖掘专题讲座

2023年,望繁信科技联合创始人兼CTO李进峰博士受邀在上海外国语大学国际工商管理学院(以下简称“上外管院”)开展专题讲座,畅谈流程挖掘的发展及对企业数字化转型的价值。演讲吸引了上外教授和来自各行各业的领军企业学员百余人。 …

easyExcel使用模版填充excel,合并单元格

一、最终效果 二、制作模版 1、制作填充模版 模版在代码中保存的位置 2、Controller /*** 下载模板*/ RequestMapping(value "exportData") public void exportData(KqKqb kqKqb,HttpServletResponse response, HttpServletRequest request) throws IOExceptio…

高级算法设计与分析 学习笔记10 平摊分析

动态表,可以变长。 一溢出就另起一个两倍大小的表。 可以轻易证明把n个数字放进去的时间复杂度是O(n),n n/2 n/4……也就2n,插入数字本身也就是n,加起来最多不超过3n. 这种复杂度究竟是怎么算的?毕竟每次插入复杂度…

Vulhub zico 2靶机详解

项目地址 https://download.vulnhub.com/zico/zico2.ova实验过程 将下载好的靶机导入到VMware中,设置网络模式为NAT模式,然后开启靶机虚拟机 使用nmap进行主机发现,获取靶机IP地址 nmap 192.168.47.1-254根据对比可知Zico 2的一个ip地址为…

阿里云ACP认证考试题库

最近有好些同学,考完阿里云ACP了,再来跟我反馈:自己花700买的阿里云ACP题库,结果答案是错的! 或者考完后发现,买的阿里云ACP题库覆盖率只有50%! 为避免大家继续踩坑,给大家分享一个阿…

短视频去水印解析api接口使用文档

短视频去水印解析api接口,支持各大平台短视频和图集。 请求示例:https://www.dspqsy.vip/spapi?key密钥&url短视频链接 返回数据格式:JSON 请求方式:GET/POST 请求参数:url (短视频分享的URL) PHP 源码&…

从存储到人工智能洞察: 利用 MinIO 和 Polars 简化数据管道

将 MinIO 的高性能、可扩展企业对象存储的强大功能与 Polars(闪电般快速的 DataFrame 库)的快速内存数据处理功能相结合,可以显著提高数据管道的性能。在 AI 工作流中尤其如此,其中预处理大型数据集和执行特征选择是关键步骤。在这…