开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
今天来学习如何用Go使用RabbitMQ,跟着我的步伐来一起学习吧!
安装RabbitMQ
在学习RabbitMQ之前,先要安装它,这里介绍通过Docker容器来安装,在Win10环境下安装Docker Destop 下载定制,按照提示一步一步安装,需要在本机上开启虚拟功能
开启虚拟功能的命令:
- 启用适用于 Linux 的 Windows 子系统
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart - 启用Windows虚拟机功能
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart - 将WSL2设置为默认版本
wsl --set-default-version 2 - 打开电脑端的Microsoft Store,安装Linux子系统,如下图所示
安装镜像
在Docker Hub中拉取最新的RabbitMQ镜像:
docker pull rabbitmq(不带管理界面,需要手动安装,后续会介绍)
或者 docker pull rabbitmq:3.9.26-management
启动容器: docker run -d --hostname localhost --name rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq
- --hostname:指定容器主机名称
- --name:指定容器名称-p:将mq端口号映射到本地
- -p:指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
启动之后访问RabbitMQ Management,在浏览器中输入http://localhost:15672会出现无法访问的情况, 需要进入容器内部,手动打开Web管理界面
进入RabbitMQ容器:
rabbitmq替换为自己的容器名或者id
docker exec -it rabbitmq /bin/bash
然后运行下面命令
rabbitmq-plugins enable rabbitmq_management
出现下面内容表示打开成功
最后输入账号密码: 默认是admin
点击Channel会遇到Stats in management UI are disabled on this node问题
因为前面拉取的镜像不带后面不带management,启动rabbitmq后是会报错的,需要再手动安装; 所以推荐直接拉取后面带management版本的,例如:docker pull rabbitmq:3.9.26-management
cd /etc/rabbitmq/conf.d/
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
exit
重启容器
到此就安装成功了,显示效果如下:
RabbitMQ的入门
概念
RabbitMQ是一个消息代理:它是一个中间服务者,负责接收和转发消息
RabbitMQ:只是接收、存储和转发二进制数据块--各种消息,而不去处理数据
发送消息:对应生产者,用来产生数据
队列:是RabbitMQ内部的存储数据的名称,队列只受到主机内存和磁盘大小的限制,实际上就是一个大容量的缓冲区,很多个生产者可以向一个队列中发消息(n:1),许多消费者也可以尝试从一个队列接收数据
接收消息:对应消费者,等待接收数据
编写"Hello World"
在下图中,Producer是我们的生产者,Consumer是我们的消费者,中间的框是消息缓冲区。
使用go get 安装amqp协议
go get github.com/streadway/amqp
发送者
先建立一个socket连接,并为我们处理协议版本协商和认证等,接下来,我们创建一个通道,这个通道用于提供发送数据所需的API,接着还需要声明要发送到的队列信息。
// 处理错误返回信息
func DoError(err error, msg string) {
if err != nil {
log.Fatalf("%s:%s", msg, err)
}
}
func main() {
conn, err := amqp.Dial("amqp://admin:admin@localhost:5672/")
DoError(err, "Failed connect to RabbitMQ!")
defer conn.Close()
ch, err := conn.Channel()
DoError(err, "Failed to open a channel")
defer ch.Close()
queue, err := ch.QueueDeclare(
"YYQQ", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
DoError(err, "Failed to declare a queue")
content := "I am a student"
err = ch.Publish("", queue.Name, false, false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(content),
})
DoError(err, "Failed to publish a message")
}
接受者
我们打开一个连接和一个通道,并声明要消耗的队列。这里的声明要和send发布到的队列匹配。
package main
import (
"github.com/streadway/amqp"
"log"
)
func DoError(err error, msg string) {
if err != nil {
log.Fatalf("%s:%s", msg, err)
}
}
func main() {
conn, err := amqp.Dial("amqp://admin:admin@localhost:5672/")
DoError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
ch, err := conn.Channel()
DoError(err, "Failed to open a channel")
defer ch.Close()
queue, err := ch.QueueDeclare(
"YYQQ", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
DoError(err, "Failed to declare a queue")
content, err := ch.Consume(queue.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
DoError(err, "Failed to register a consumer")
var wait chan struct{}
go func() {
for msg := range content {
log.Printf("Received a message %s", msg.Body)
}
}()
<-wait
}
运行两个脚本
go run receive.go
go run send.go
得到的结果如下:
总结
今天浅谈了Go与RabbitMQ(一),还有很多相关的知识后面会继续深入,对于刚入门go语言的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!