Go操作RabbitMQ_go调用rabbitmq(2),2024年最新【绝对干货

延迟队列插件

  1. 地址

Releases · rabbitmq/rabbitmq-delayed-message-exchange · GitHub

查看插件挂载目录

docker volume inspect mq-plugins

将插件上传到 /var/lib/docker/volumes/mq-plugins/_data 目录下

docker exec -it mq rabbitmq-plugins enable rabbitmq_delayed_message_exchange

运行

创建docker网络

docker network create test

启动容器

docker run
-e RABBITMQ_DEFAULT_USER=test
-e RABBITMQ_DEFAULT_PASS=123123
-v mq-plugins:/plugins
–name mq
–hostname mq
-p 15672:15672
-p 5672:5672
–network test
-d
rabbitmq:3.12-management

RabbitMQ 常用端口以及作用

端口功能
5672AMQP(Advanced Message Queuing Protocol)协议的默认端口,用于客户端与RabbitMQ服务器之间的通信。
15672RabbitMQ的管理界面,默认使用HTTP协议,用于监控和管理RabbitMQ服务器。
4369Erlang分布式节点通信端口,用于RabbitMQ节点之间的通信。
25672Erlang分布式节点通信端口,用于集群中的内部通信。
5671安全的AMQP端口,使用TLS/SSL进行加密通信。

架构图

  • publisher:生产者,也就是发送消息的一方
  • consumer:消费者,也就是消费消息的一方
  • queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理
  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue

工作模式

1. 简单模式(Simple)

  • 特点

    • 生产者直接将消息发送到队列中,消费者从队列中获取消息并进行处理。
  • 消息一旦被消费,就会从队列中移除。
  • 真实应用场景

    • 电子邮件通知系统:生产者将待发送的邮件放入队列,消费者负责从队列中获取邮件并发送。
  • 优点

    • 实现简单,易于理解和部署。
  • 适用于单一消费者场景。
  • 缺点

    • 没有消息持久化,一旦 RabbitMQ 服务器重启,队列中的消息将会丢失。
1.1. 目录结构

simple

-mq

–-rabbitmq.go //这个是RabbitMQ的封装

-SimplePublish

–-mainSimplePublish.go //生产者发送消息

-SimpleRecieve

–-mainSimpleRecieve.go // 消费者接受消息

1.2. 代码实现
1.2.1. rabbitmq.go

package mq

import (
“fmt”
“log”

“github.com/streadway/amqp”
)

// MQURL amqp://user:password@host:port/vhost
// amqp://是固定参数,这个信息是固定不变的。后面两个是用户名密码ip地址端口号Virtual Host
// 如果vhost是“/”就输入/%2F,/%2F代表斜杠
const MQURL = “amqp://test:123123@127.0.0.1:5672/%2F”

// RabbitMQ rabbitMQ结构体
type RabbitMQ struct {
conn *amqp.Connection
channel *amqp.Channel
//队列名称
QueueName string
//交换机名称
Exchange string
//bind Key 名称
Key string
//连接信息
Mqurl string
}

// NewRabbitMQ 创建结构体实例
func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
return &RabbitMQ{QueueName: queueName, Exchange: exchange, Key: key, Mqurl: MQURL}
}

// Destory 断开channel 和 connection
func (r *RabbitMQ) Destory() {
err := r.channel.Close()
if err != nil {
return
}
err = r.conn.Close()
if err != nil {
return
}
}

// 错误处理函数
func (r *RabbitMQ) failOnErr(err error, message string) {
if err != nil {
log.Fatalf(“%s:%s”, message, err)
}
}

// NewRabbitMQSimple 创建简单模式下RabbitMQ实例
func NewRabbitMQSimple(queueName string) *RabbitMQ {
//创建RabbitMQ实例
rabbitmq := NewRabbitMQ(queueName, “”, “”)
var err error
//获取connection
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, “failed to connect rabb”+
“itmq!”)
//获取channel
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, “failed to open a channel”)
return rabbitmq
}

// PublishSimple simple模式队列生产
func (r *RabbitMQ) PublishSimple(message string) {
//1.申请队列,如果队列不存在会自动创建,存在则跳过创建
_, err := r.channel.QueueDeclare(
// queue:队列名称
r.QueueName,
//durable:是否持久化,当mq重启之后,还在
true,
//exclusive:是否独占即只能有一个消费者监听这个队列
false,
//autoDelete:是否自动删除。当没有Consumer时,自动删除掉
false,
//noWait:是否阻塞处理。true:不阻塞,false:阻塞
false,
//arguments:其他属性
nil,
)
if err != nil {
fmt.Println(err)
}
//调用channel 发送消息到队列中
r.channel.Publish(
r.Exchange,
r.QueueName,
//如果为true,根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还给发送者
false,
//如果为true,当exchange发送消息到队列后发现队列上没有消费者,则会把消息返还给发送者
false,
amqp.Publishing{
ContentType: “text/plain”,
Body: []byte(message),
})
}

// ConsumeSimple simple模式下消费者
func (r *RabbitMQ) ConsumeSimple() {
//1.申请队列,如果队列不存在会自动创建,存在则跳过创建
q, err := r.channel.QueueDeclare(
//队列名称
r.QueueName,
//是否持久化
true,
//是否自动删除
false,
//是否具有排他性
false,
//是否阻塞处理
false,
//额外的属性
nil,
)
if err != nil {
fmt.Println(err)
}
//接收消息
msgs, err := r.channel.Consume(
q.Name, // queue
//用来区分多个消费者
“”, // consumer
//是否自动应答
true, // auto-ack
//是否独有
false, // exclusive
//设置为true,表示 不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者
false, // no-local
//列是否阻塞
false, // no-wait
nil, // args
)
if err != nil {
fmt.Println(err)
}

forever := make(chan bool)
//启用协程处理消息
go func() {
for d := range msgs {
//消息逻辑处理,可以自行设计逻辑
log.Printf(“Received a message: %s”, d.Body)

}
}()

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

}

1.2.2. SimplePublish.go

package main

import (
“fmt”
“qiutian.com/study/02.rabbitmq/Simple/mq”
)

func main() {
rabbitmq := mq.NewRabbitMQSimple(“hello.queue1”)
rabbitmq.PublishSimple(“Hello akita!”)
fmt.Println(“发送成功!”)
}

1.2.3. mainSimpleRecieve.go

package main

import (
“qiutian.com/study/02.rabbitmq/Simple/mq”
)

// simple模式消费者
func main() {
// queueName 替换成你自己的队列名
rabbitmq := mq.NewRabbitMQSimple(“hello.queue1”)
rabbitmq.ConsumeSimple()
}

2. 工作模式(Work)

  • 特点

    • 多个消费者同时从同一个队列中获取消息并处理,每个消息只能被一个消费者处理。
  • 消息在被消费者处理后会从队列中移除。
  • 真实应用场景

    • 任务分发系统:多个消费者同时从队列中获取任务,每个消费者处理一个任务,以实现任务的负载均衡。
  • 优点

    • 可以通过增加消费者来提高消息处理的并发性。
  • 缺点

    • 没有消息持久化,一旦 RabbitMQ 服务器重启,队列中的消息将会丢失。
2.1. 目录结构

Work

-mq

–-rabbitmq.go //这个是RabbitMQ的封装

-WorkPublish

–-mainWorkPublish.go //生产者发送消息

-WorkRecieve1

–-mainWorkRecieve1.go // 消费者接受消息

-WorkRecieve2

–-mainWorkRecieve2.go // 消费者接受消息

2.2. 代码实现
2.2.1. rabbitmq.go

package mq

import (
“fmt”
“log”

“github.com/streadway/amqp”
)

// MQURL amqp://user:password@host:port/vhost
// amqp://是固定参数,这个信息是固定不变的。后面两个是用户名密码ip地址端口号Virtual Host
// 如果vhost是“/”就输入/%2F,/%2F代表斜杠
const MQURL = “amqp://test:123123@127.0.0.1:5672/%2F”
// RabbitMQ rabbitMQ结构体
type RabbitMQ struct {
conn *amqp.Connection
channel *amqp.Channel
//队列名称
QueueName string
//交换机名称
Exchange string
//bind Key 名称
Key string
//连接信息
Mqurl string
}

// NewRabbitMQ 创建结构体实例
func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
return &RabbitMQ{QueueName: queueName, Exchange: exchange, Key: key, Mqurl: MQURL}
}

// Destory 断开channel 和 connection
func (r *RabbitMQ) Destory() {
r.channel.Close()
r.conn.Close()
}

// 错误处理函数
func (r *RabbitMQ) failOnErr(err error, message string) {
if err != nil {
log.Fatalf(“%s:%s”, message, err)
panic(fmt.Sprintf(“%s:%s”, message, err))
}
}

// NewRabbitMQWork 创建work模式下RabbitMQ实例
func NewRabbitMQWork(queueName string) *RabbitMQ {
//创建RabbitMQ实例
rabbitmq := NewRabbitMQ(queueName, “”, “”)
var err error
//获取connection
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, “failed to connect rabb”+
“itmq!”)
//获取channel
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, “failed to open a channel”)
return rabbitmq
}

// PublishWork work模式队列生产
func (r *RabbitMQ) PublishWork(message string) {
//1.申请队列,如果队列不存在会自动创建,存在则跳过创建
_, err := r.channel.QueueDeclare(
// queue:队列名称
r.QueueName,
//durable:是否持久化,当mq重启之后,还在
true,
//exclusive:是否独占即只能有一个消费者监听这个队列
false,
//autoDelete:是否自动删除。当没有Consumer时,自动删除掉
false,
//noWait:是否阻塞处理。true:不阻塞,false:阻塞
false,
//arguments:其他属性
nil,
)
if err != nil {
fmt.Println(err)
}
//调用channel 发送消息到队列中
r.channel.Publish(
r.Exchange,
r.QueueName,
//如果为true,根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还给发送者
false,
//如果为true,当exchange发送消息到队列后发现队列上没有消费者,则会把消息返还给发送者
false,
amqp.Publishing{
ContentType: “text/plain”,
Body: []byte(message),
})
}

// ConsumeWork work 模式下消费者
func (r *RabbitMQ) ConsumeWork() {
//1.申请队列,如果队列不存在会自动创建,存在则跳过创建
q, err := r.channel.QueueDeclare(
//队列名称
r.QueueName,
//是否持久化
true,
//是否自动删除
false,
//是否具有排他性
false,
//是否阻塞处理
false,
//额外的属性
nil,
)
if err != nil {
fmt.Println(err)
}
//接收消息
msgs, err := r.channel.Consume(
q.Name, // queue
//用来区分多个消费者
“”, // consumer
//是否自动应答
true, // auto-ack
//是否独有
false, // exclusive
//设置为true,表示 不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者
false, // no-local
//列是否阻塞
false, // no-wait
nil, // args
)
if err != nil {
fmt.Println(err)
}

forever := make(chan bool)
//启用协程处理消息
go func() {
for d := range msgs {
//消息逻辑处理,可以自行设计逻辑
log.Printf(“Received a message: %s”, d.Body)

}
}()

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

}

2.2.2. mainWorkPublish.go

package main

import (
“fmt”
“qiutian.com/study/02.rabbitmq/Work/mq”
“strconv”
“time”
)

func main() {
rabbitmq := mq.NewRabbitMQWork(“hello.queue1”)
for i := 0; i <= 100; i++ {
rabbitmq.PublishWork(“Hello akita!” + strconv.Itoa(i))
time.Sleep(1 * time.Second)
fmt.Println(i)
}
}

2.2.3. mainWorkRecieve1.go

package main

import (
“qiutian.com/study/02.rabbitmq/Work/mq”
)

func main() {
// queueName 替换成你自己的队列名
rabbitmq := mq.NewRabbitMQWork(“hello.queue1”)
rabbitmq.ConsumeWork()
}

2.2.4. mainWorkRecieve2.go

package main

import (
“qiutian.com/study/02.rabbitmq/Work/mq”
)

func main() {
// queueName 替换成你自己的队列名
rabbitmq := mq.NewRabbitMQWork(“hello.queue1”)
rabbitmq.ConsumeWork()
}

3. 订阅模式(Publish)

TIPS:

在订阅消费者模式下,消费者后监听到的数据取决于它开始监听的时间。如果消费者在生产者生产数据之前开始监听,那么它将不会消费到生产者在开始监听之前发布的数据。只有在消费者开始监听之后,生产者发布的数据才会被消费者接收和处理。因此,如果你想让消费者消费之前发布的数据,你需要确保消费者在生产者发布数据之后开始监听。

  • 特点

    • 生产者将消息发送到一个交换机中,交换机将消息广播给所有绑定了该交换机的队列。
  • 每个消息都会被交换机广播给所有绑定了该交换机的队列。
  • 真实应用场景

    • 新闻推送系统:生产者将最新的新闻发布到交换机中,每个订阅者(消费者)都会收到相同的新闻。
  • 优点

    • 实现了消息的广播功能,适用于多个消费者同时接收相同消息的场景。
  • 缺点

    • 无法根据消费者的兴趣或条件选择性地接收消息。
3.1. 目录结构

3.2. 代码实现
3.2.1.1. rabbitmq.go

package mq

import (
“fmt”
“log”

“github.com/streadway/amqp”
)

// MQURL amqp://user:password@host:port/vhost
// amqp://是固定参数,这个信息是固定不变的。后面两个是用户名密码ip地址端口号Virtual Host
// 如果vhost是“/”就输入/%2F,/%2F代表斜杠
const MQURL = “amqp://test:123123@127.0.0.1:5672/%2F”

// RabbitMQ rabbitMQ结构体
type RabbitMQ struct {
conn *amqp.Connection
channel *amqp.Channel
//队列名称
QueueName string
//交换机名称
Exchange string
//bind Key 名称
Key string
//连接信息
Mqurl string
}

// NewRabbitMQ 创建结构体实例
func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
return &RabbitMQ{QueueName: queueName, Exchange: exchange, Key: key, Mqurl: MQURL}
}

// Destory 断开channel 和 connection
func (r *RabbitMQ) Destory() {
r.channel.Close()
r.conn.Close()
}

// 错误处理函数
func (r *RabbitMQ) failOnErr(err error, message string) {
if err != nil {
log.Fatalf(“%s:%s”, message, err)
panic(fmt.Sprintf(“%s:%s”, message, err))
}
}

// NewRabbitMQPub 创建Pub模式下RabbitMQ实例
func NewRabbitMQPub(exchangeName string) *RabbitMQ {
//创建RabbitMQ实例
rabbitmq := NewRabbitMQ(“”, exchangeName, “”)
var err error
//获取connection
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, “failed to connect rabb”+
“itmq!”)
//获取channel
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, “failed to open a channel”)
return rabbitmq
}

// PublishPub Pub模式队列生产
func (r *RabbitMQ) PublishPub(message string) {
//1.尝试创建交换机
err := r.channel.ExchangeDeclare(
//交换机名称
r.Exchange,
//交换机类型
“fanout”,
//是否持久化
true,
//是否自动删除
false,
//true表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
false,
//是否阻塞处理
false,
//其他属性
nil,
)
r.failOnErr(err, “Failed to declare an exchange”)

//2.发送消息
//发送消息
//参数:
//1.交换机
//2.队列,
//3.是否强制性路由到队列,如果为true,根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还
//给发送者
//4.是否立即发送
//5.其他属性
//6.发送消息的内容
//调用channel 发送消息到队列中
r.channel.Publish(
r.Exchange,
“”,
//如果为true,根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还给发送者
false,
//如果为true,当exchange发送消息到队列后发现队列上没有消费者,则会把消息返还给发送者
false,
amqp.Publishing{
ContentType: “text/plain”,
Body: []byte(message),
})
}

// ConsumePub pub 模式下消费者
func (r *RabbitMQ) ConsumePub() {
//1.试探性创建交换机
err := r.channel.ExchangeDeclare(
// 交换机名称
r.Exchange,
//交换机类型
“fanout”,
//是否持久化
true,
// 是否自动删除
false,
//YES表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
false,
//
false,
nil,
)
r.failOnErr(err, “Failed to declare an exchange”)

//2.试探性创建队列,这里注意队列名称不要写
q, err := r.channel.QueueDeclare(
//随机生产队列名称
“”,
//是否持久化
false,
//是否自动删除
false,
//是否具有排他性
true,
//是否阻塞处理
false,
//其他参数
nil,
)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
img

//2.试探性创建队列,这里注意队列名称不要写
q, err := r.channel.QueueDeclare(
//随机生产队列名称
“”,
//是否持久化
false,
//是否自动删除
false,
//是否具有排他性
true,
//是否阻塞处理
false,
//其他参数
nil,
)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-NrECcHK3-1712518580170)]
[外链图片转存中…(img-tVpAVsWE-1712518580170)]
[外链图片转存中…(img-OEBb3JW9-1712518580171)]
[外链图片转存中…(img-SaqY6Xet-1712518580171)]
[外链图片转存中…(img-hHmpuHON-1712518580171)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
[外链图片转存中…(img-eCsKR515-1712518580171)]

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值