一、RabbitMQ 基础概念
AMQP 协议
AMQP(高级消息队列协议):与语言、平台无关的消息协议,RabbitMQ 基于该协议。
Spring AMQP 简介
Spring AMQP 是基于 AMQP 协议封装的 API 规范,分为两部分:
spring-amqp:基础抽象层spring-rabbit:底层 RabbitMQ 具体实现
二、Go 客户端安装
注意:这里有两套 Go 客户端
- 新版官方:
rabbitmq-amqp-go-client(AMQP 1.0)- 社区常用:
streadway/amqp(AMQP 0-9-1,下面 Demo 用的这个,学习推荐)
# 新版官方客户端安装
go get github.com/rabbitmq/rabbitmq-amqp-go-client
导入:
Go
import (
"context"
"log"
rmq "github.com/rabbitmq/rabbitmq-amqp-go-client/pkg/rabbitmqamqp"
)
下面示例代码使用的是
streadway/amqp(AMQP0-9-1,目前学习最简单,和 SpringAMQP 底层协议一致)
三、简单模型:生产者直接发消息到队列(Simple 模型)
流程:Publisher → Queue → Consumer 案例:
simple.queue
- 在 RabbitMQ 控制台创建队列
simple.queue(代码里QueueDeclare是幂等,不存在自动创建) - 生产者发送消息到队列
- 消费者监听队列,接收消息
SpringAMQP 开发步骤对照(方便 Java 转 Go 理解)
- 引入 RabbitMQ 依赖
- 配置 RabbitMQ 服务信息:
host、port、virtual-host、username、password - 发送消息:使用
RabbitTemplate - 消费消息:使用
@RabbitListener注解监听队列
Go 生产者代码(send.go)
等价 Spring
rabbitTemplate.convertAndSend(queueName, msg)
Go
package main
import (
"fmt"
"github.com/streadway/amqp"
)
func main() {
// 1. 连接 rabbitmq
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
if err != nil {
panic(err)
}
defer conn.Close()
// 2. 创建通道
ch, err := conn.Channel()
if err != nil {
panic(err)
}
defer ch.Close()
queueName := "simple.queue"
// 3. 声明队列:幂等。队列存在则不操作,不存在自动创建
_, err = ch.QueueDeclare(
queueName,
false, // durable:是否持久化
false, // autoDelete:是否自动删除
false, // exclusive:独占队列
false, // noWait
nil, // args:额外参数
)
if err != nil {
panic(err)
}
msg := "hello, amqp!"
// 4. 发布消息
err = ch.Publish(
"", // exchange:空=默认交换机,和Spring行为一致
queueName, // routingKey:直接填队列名,消息直接路由到此队列
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(msg),
},
)
if err != nil {
panic(err)
}
fmt.Printf("发送消息成功:%s\n", msg)
}
Go 消费者代码(consumer.go)
等价 Spring
@RabbitListener(queues = "simple.queue"),持续监听队列
Go
package main
import (
"fmt"
"github.com/streadway/amqp"
"log"
)
func main() {
// 1. 连接RabbitMQ
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
if err != nil {
log.Fatalf("连接失败: %v", err)
}
defer conn.Close()
// 2. 创建通道
ch, err := conn.Channel()
if err != nil {
log.Fatalf("打开通道失败: %v", err)
}
defer ch.Close()
queueName := "simple.queue"
// 3. 声明队列(幂等)
_, err = ch.QueueDeclare(
queueName,
false,
false,
false,
false,
nil,
)
if err != nil {
log.Fatalf("声明队列失败: %v", err)
}
// 4. 注册消费者,开始消费消息
msgs, err := ch.Consume(
queueName, // 监听队列名
"", // consumer
true, // autoAck=true:收到消息自动确认,和Spring默认近似
false, // exclusive
false, // noLocal
false, // noWait
nil, // args
)
if err != nil {
log.Fatalf("注册消费失败: %v", err)
}
fmt.Println("Go消费者启动,监听 simple.queue ...")
// 循环读取消息,持续处理消息
for d := range msgs {
msg := string(d.Body)
fmt.Printf("go 消费者接收到消息:[%s]\n", msg)
fmt.Println("消息处理完成")
}
}
四、核心要点总结
- 连接地址不要写错:
amqp://账号:密码@ip:5672/ QueueDeclare幂等特性:重复调用不会报错,不存在则新建队列- Simple 模型:空交换机,routingKey 直接写队列名,消息直接投递队列
autoAck:自动确认,消息收到后 MQ 立刻删除消息;生产环境一般关闭,手动 ACK 保证可靠性- SpringAMQP 和 Go streadway/amqp 底层都是 AMQP0-9-1,可以对照理解学习