rabbitMQ的简单使用

rabbitMQ的介绍

RabbitMQ是一个开源的消息代理和队列服务器,主要用于在不同的应用程序之间传递消息。它基于AMQP(Advanced Message Queuing Protocol)协议,提供了一种可靠的方式来处理异步通信。RabbitMQ使用Erlang语言编写,具有高可用性、可伸缩性和可靠性。

windows下安装

1.安装Erlang,官网:erlang
在这里插入图片描述

2.安装rabbitmq,官网:rabbitmq
在这里插入图片描述

启动rabbitmq

黑窗口进入…/sbin输入命令:

rabbitmq-plugins enable rabbitmq_management

在浏览器中输入地址查看是否安装成功:http://127.0.0.1:15672/
在这里插入图片描述

使用默认账号密码登录:guest/guest

rabbitMQ的优缺点

2007 年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。

优点:

  • 由于 erlang 语言的高并发特性,性能较好;
  • 吞吐量到万级,MQ功能比较完备、健壮、稳定、易用、跨平台、支持多种语言如Python、Java等,支持AJAX 文档齐全;
  • 开源提供的管理界面非常棒,用起来很好用,社区活跃度高;
  • 更新频率相当高。

缺点:

  • 商业版需要收费,学习成本较高。
  • 选用场景:结合 erlang 语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,管理界面用起来十分方便,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的 RabbitMQ。

为什么使用rabbitmq

1️⃣ 高并发的流量削峰

举个例子,假设某订单系统每秒最多能处理一万次订单,也就是最多承受的10000qps,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
在这里插入图片描述
2️⃣ 应用解耦

以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,中单用户感受不到物流系统的故障,提升系统的可用性。
在这里插入图片描述

3️⃣ 异步处理

有些服务间调用是异步的,例如 A 调用 B,B 需要花费很长时间执行,但是 A 需要知道 B 什么时候可以执行完,以前一般有两种方式,A 过一段时间去调用 B 的查询 api 查询。或者 A 提供一个 callback api, B 执行完之后调用 api 通知 A 服务。这两种方式都不是很优雅,使用消息队列,可以很方便解决这个问题,A 调用 B 服务后,只需要监听 B 处理完成的消息,当 B 处理完成后,会发送一条消息给 MQ,MQ 会将此消息转发给 A 服务。这样 A 服务既不用循环调用 B 的查询 api,也不用提供 callback api。同样B 服务也不用做这些操作。A 服务还能及时的得到异步处理成功的消息。

在这里插入图片描述

简单示例:

客户端(发消息):

package main

import (
	"context"
	"log"
	"os"
	"strings"
	"time"

	amqp "github.com/rabbitmq/amqp091-go"
)

// 检查每个 AMQP电话
func failOnError(err error, msg string) {
	if err != nil {
		log.Panicf("%s: %s", msg, err)
	}
}

// 连接到 RabbitMQ 服务器
func main() {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()
	//创建一个通道,这是大多数 API 用于获取 完成的事情驻留
	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()
	//声明一个队列供我们发送到;然后我们可以发布一条消息 到队列
	q, err := ch.QueueDeclare(
		"task_queue", // name
		true,         // durable 持久
		false,        // delete when unused
		false,        // exclusive
		false,        // no-wait
		nil,          // arguments
	)
	failOnError(err, "Failed to declare a queue")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	/*body := "Hello World!"
	err = ch.PublishWithContext(ctx,
		"",     // exchange
		q.Name, // routing key
		false,  // mandatory
		false,  // immediate
		amqp.Publishing{
			ContentType: "text/plain",
			Body:        []byte(body),
		})
	failOnError(err, "Failed to publish a message")
	log.Printf(" [x] Sent %s\n", body)*/

	//允许从命令行发送任意消息
	body := bodyFrom(os.Args)
	err = ch.PublishWithContext(ctx,
		"",     // exchange
		q.Name, // routing key
		false,  // mandatory
		false,
		amqp.Publishing{
			DeliveryMode: amqp.Persistent,
			ContentType:  "text/plain",
			Body:         []byte(body),
		})
	failOnError(err, "Failed to publish a message")
	log.Printf(" [x] Sent %s", body)
}

func bodyFrom(args []string) string {
	var s string
	if (len(args) < 2) || os.Args[1] == "" {
		s = "hello"
	} else {
		s = strings.Join(args[1:], " ")
	}
	return s
}

服务端(接收消息):

package main

import (
	"bytes"
	"log"
	"time"

	amqp "github.com/rabbitmq/amqp091-go"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Panicf("%s: %s", msg, err)
	}
}

func main() {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()

	q, err := ch.QueueDeclare(
		"task_queue", // name
		true,         // durable
		false,        // delete when unused
		false,        // exclusive
		false,        // no-wait
		nil,          // arguments
	)
	failOnError(err, "Failed to declare a queue")
	//告诉 RabbitMQ 不要给超过 一次向工作人员发送一条消息。
	//或者,换句话说,不要派遣 向工作人员发送一条新消息,直到它处理并确认 上一个。
	//相反,它会将其分派给下一个尚未忙碌的工作人员。
	err = ch.Qos(
		1,     // prefetch count
		0,     // prefetch size
		false, // global
	)
	failOnError(err, "Failed to set QoS")
	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		false,  // auto-ack  发送适当的确认 来自工作人员(这确认单次交付), 一旦我们完成了一项任务
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	failOnError(err, "Failed to register a consumer")

	var forever chan struct{}

	/*go func() {
		for d := range msgs {
			log.Printf("Received a message: %s", d.Body)
		}
	}()*/

	//需要 为邮件正文中的每个点伪造一秒钟的工作。它会弹出 来自队列的消息并执行任务
	go func() {
		for d := range msgs {
			log.Printf("Received a message: %s", d.Body)
			dotCount := bytes.Count(d.Body, []byte("."))
			t := time.Duration(dotCount)
			time.Sleep(t * time.Second)
			log.Printf("Done")
			d.Ack(false)
		}
	}()

	log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
	<-forever
}

运行效果:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IT入门知识第三部分《软件开发》(3/10)

目录 IT入门知识大纲第三部分《软件开发》 1. 软件开发生命周期&#xff08;SDLC&#xff09; 1.1 需求分析 1.2 软件设计 1.3 程序编码 1.4 软件测试 1.5 项目部署 1.6 运行维护 2. 软件开发方法论 2.1 瀑布模型 2.2 敏捷开发 2.2.1 Scrum 2.2.2 Kanban 2.3 Dev…

告别盲目投放,Xinstall全方位监测App广告效果

在移动互联网高速发展的今天&#xff0c;App广告已成为品牌与消费者沟通的重要桥梁。然而&#xff0c;如何确保广告投放的精准性和效果性&#xff0c;成为广告主们关注的焦点。在这个数据驱动的时代&#xff0c;Xinstall以其专业的App广告效果统计功能&#xff0c;为广告主们提…

将Typora中图片从指定路径移动到当前文件夹下(准确位置为:XX.md文件所在目录/XX.assets/)

1、背景介绍 最开始时候,将复制到Typora中的图片放在了指定位置。但是在进行迁移(在别的电脑上打开md文件),会发现发送过来的文件不包含图片,导致文件内容缺失。解决办法就是将图片放在XX.md文件所在目录/XX.assets/。 2、方法 2.1 做好文件备份 2.2 替换图片链接中的…

使用MyBatisPlus让数据库和实体类字段自动映射

文章目录 使用MyBatisPlus让数据库和实体类字段自动映射需求场景假如没有映射把映射放到sql语句中使用MyBatisPlus提供的注解简化映射 使用MyBatisPlus让数据库和实体类字段自动映射 需求场景 数据库表中的字段名字&#xff0c;与实体类中的属性名字不一致&#xff0c;我们想…

使用PaddleNLP 从0构建一个属于你自己的心理大模型

项目源于&#xff1a;EmoLLM心理大模型,一直就有用paddle实践心理大模型的想法&#xff0c;终于实现了哈~。接下来就手把手带大家一块做一个心理大模型吧&#xff01;&#xff01;&#xff01; 简单画了个框架图&#xff1a; 环境配置 In [ ] # !git clone -b develop https…

新安装的gcc编译出现编译器内部错误

在原本的环境中已经安装gcc了&#xff0c;但是版本比较低&#xff0c;想用新的版本。 重新下载安装gcc源码编译安装 make install安装好之后想用新的gcc来编译 先改下头文件搜索路径&#xff0c;xxxxxx就是安装后的include/c/xxx/这个路径 CPLUS_INCLUDE_PATH xxxxxx:$CPL…

建筑幕墙甲级设计资质:申请条件与评分标准

建筑幕墙甲级设计资质的申请条件与评分标准可以清晰归纳如下&#xff1a; 申请条件 一、企业基本情况 独立企业法人资格&#xff1a;企业需具有独立企业法人资格。注册资本&#xff1a;注册资本不少于300万元人民币。 二、技术人员条件 主要技术负责人或总工程师&#xff…

Nuxt.js 深入浅出:目录结构与文件组织详解

title: Nuxt.js 深入浅出&#xff1a;目录结构与文件组织详解 date: 2024/6/18 updated: 2024/6/18 author: cmdragon excerpt: 摘要&#xff1a;本文详述了Nuxt.js框架中关键目录与配置文件的作用及使用方法&#xff0c;包括布局设定、页面结构管理、插件集成、静态资源处理…

1999-2020年各地级市农村居民人均纯收入数据

1999-2020年各地级市农村居民人均纯收入数据 1、时间&#xff1a;1999-2020年 2、指标&#xff1a;年份、城市、农村居民人均纯收入 3、来源&#xff1a;区域年鉴、各省市年鉴 4、范围&#xff1a;地级市&#xff0c;具体每年城市数量参看下文图片&#xff0c;具体城市名单…

macbook屏幕录制技巧,这2个方法请你收好

在当今数字化时代&#xff0c;屏幕录制成为了一项不可或缺的技能&#xff0c;无论是教学演示、游戏直播&#xff0c;还是软件操作教程&#xff0c;屏幕录制都能帮助我们更直观地传达信息。MacBook作为苹果公司的标志性产品&#xff0c;其屏幕录制功能也备受用户关注。本文将详细…

【小白专用24.6.18】C# SqlSugar:连接数据库实现简单的,增、删、改、查

【小白专用 已验证24.6.18】C# SqlSugar操作MySQL数据库实现增删改查-CSDN博客 通过NuGet包管理器搜索SqlSugar&#xff08;MySql还要安装MySql.Data、Newtonsoft.Json&#xff09;包并安装 SqlSugarClient db new SqlSugarClient(new ConnectionConfig(){ConnectionString …

计数类DP——AcWing 900. 整数划分

计数类DP 定义 计数类DP主要是通过动态规划的方法来计算满足特定条件的方案数、组合数等数量相关的问题。 运用情况 需要计算不同排列、组合或情况的数量。问题具有明显的阶段性&#xff0c;且每个阶段的选择会对后续阶段产生影响。可以通过逐步构建较小规模问题的解来推导…

mumu 模拟器如何模拟指纹识别?

最近在帮朋友解决一些任务时&#xff0c;有些比较复杂的任务需要批量使用模拟器&#xff0c;但是模拟器存在一个缺点&#xff0c;就是缺少很多物理功能&#xff0c;比如说陀螺仪、温度传感器和生物识别模块等等&#xff0c;但是有些任务是需要这些功能的。没有办法&#xff0c;…

vue3-openlayers 使用tianditu,wmts和xyz等source加载天地图切片服务

本篇介绍一下使用vue3-openlayers加载天地图切片&#xff0c;三种方法&#xff1a; 使用tianditu&#xff08;ol-source-tianditu内部实现其实用的wmts&#xff09;使用wmts&#xff08;ol-source-wmts&#xff09;使用xyz&#xff08;ol-source-xyz&#xff09; 1 需求 vue…

为什么动态代理接口中可以不加@Mapper注解

为什么动态代理接口中可以不加Mapper注解 如下图&#xff1a; 我们上面的UserMapper上面没有加Mapper注解&#xff0c;按道理来说UserMapper这个类应该是注入不到IOC容器里面的&#xff0c;但是为什么我们程序的运行效果仍然是正常的呢&#xff1f;这是因为你的启动类上加了m…

zabbix“专家坐诊”第242期问答

问题一 Q&#xff1a;snmp检查用的什么性能啊&#xff1f;设备多了就检测失败&#xff0c;实际是能通的。 A&#xff1a;把大批量请求取消&#xff0c;把异常获取不到的监控项都禁用 Q&#xff1a;是这个吧&#xff0c;显示不一样。 A&#xff1a;什么版本&#xff1f;用的是v3…

ggpicrust2包:简化和直观化微生物功能预测分析

简介 ggpicrust2是一个强大的R语言包&#xff0c;旨在简化和直观化PICRUSt2输出的分析。通过预定义的图表和函数&#xff0c;研究人员可以轻松生成关于微生物功能预测的统计图&#xff0c;并提供丰富的自定义选项。本文将演示如何使用ggpicrust2包进行分析和可视化。 安装ggp…

VBA学习(9):按指定名单一键删除工作表

今天继续给大家聊VBA编程中工作表对象的常用操作&#xff0c;主要内容是如何批量删除工作表&#xff1b;也就是删除单个工作表、删除全部工作表和删除指定名单内的工作表。 1.删除单个工作表 删除工作表需要使用到工作表对象的delete方法&#xff0c;语法格式如下&#xff1a…

Python单行代码:一招鲜,吃遍天

大家好&#xff0c;在Python编程中&#xff0c;我们时常需要高效、简洁的代码来解决复杂的问题。今天&#xff0c;我将向大家介绍10个非常有用的Python单行代码。 一行代码指的是将复杂的任务浓缩在一行代码中完成。它充分利用Python的简洁和强大&#xff0c;使代码更简洁、更…

智能穿梭,无缝连接:迈威通信助力AGV智慧物流系统高效运转

随着智能制造模式的兴起&#xff0c;在工业4.0和“中国制造2025”的推动下&#xff0c;智能物流迎来了重大的发展机遇。AGV作为智慧仓储物流系统的“关键角色”之一&#xff0c;通过联系、调节离散型物流管理系统&#xff0c;使各环节有效地衔接起来&#xff0c;实现全厂物流运…