前提条件,需要包含一个公告的获取rabbitmq channer对象的方法,
/public/mqInstance.go
package public
import "github.com/streadway/amqp"
//获取mq信道实例
func GetMqInstance() (ch *amqp.Channel, err error) {
var (
MqUrl = "amqp://guest:[email protected]:5672/"
conn *amqp.Connection
)
conn, err = amqp.Dial(MqUrl)
if err != nil {
return nil, err
}
return conn.Channel()
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"strconv"
"test.zozoo.net/mq/public"
)
const QUEUE_NAME = "hello-queue"
//简单模式生产者
func main() {
var (
err error
ch *amqp.Channel
queue amqp.Queue
)
//获取mq连接信道
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取信道失败:", err.Error())
return
}
//创建队列
queue, err = ch.QueueDeclare(
QUEUE_NAME, //队列名称
true, //是否持久化
false, //是否自动删除
false, //是否具有排他性(队列只能被一个消费者使用,并且消费者断开连接时队列就会被删除)
false, //是否不用等待服务器确认就开始消费消息
nil, //额外参数
)
if err != nil {
fmt.Println("创建队列失败:", err.Error())
return
}
//产生消息
for i := 0; i < 100; i++ {
msg := "第" + strconv.Itoa(i) + "条消息"
ch.Publish(
"",
queue.Name,
false, //为true时,exchange找不到符合条件的queue,消息会返回给生产者;false时直接扔掉
false, //为true时,当queue上没有消费者时消息不会放入到队列中
amqp.Publishing{
ContentType: "text/plain", //消息类型
Body: []byte(msg), //消息内容
},
)
}
fmt.Println("消息投递成功")
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"test.zozoo.net/mq/public"
)
//简单模式消费者
func main() {
var (
err error
ch *amqp.Channel
queue amqp.Queue
msg <-chan amqp.Delivery
)
//获取消息管道
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取消息管道失败:", err.Error())
return
}
//擦黄健消息队列
queue, err = ch.QueueDeclare(
"hello-queue",
true,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println("创建消费队列失败:", err.Error())
return
}
//消费消息
msg, err = ch.Consume(queue.Name, "", true, false, false, false, nil)
if err != nil {
fmt.Println("获取消息管道失败:", err.Error())
return
}
//循环消息管道,取出消息
for content := range msg {
fmt.Println(string(content.Body))
}
}
工作模式和简单模式一样,就是多几个消费者消费消息而已
package main
import (
"fmt"
"github.com/streadway/amqp"
"strconv"
"test.zozoo.net/mq/public"
"time"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "route-exchange"
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//声明交换机
err = ch.ExchangeDeclare(ExchangeName, "direct", true, false, false, false, nil)
if err != nil {
fmt.Println("声明交换机失败,err:", err.Error())
return
}
//发送消息
for i := 1; i < 100; i++ {
var rouKey = "consumer1"
if i%2 == 1 {
rouKey = "consumer2"
}
msg := "第" + strconv.Itoa(i) + "条消息"
ch.Publish(ExchangeName, rouKey, false, false, amqp.Publishing{
ContentType: "text/plain", //消息类型
Body: []byte(msg), //消息内容
})
time.Sleep(time.Second * 1)
}
fmt.Println("发送完成")
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"test.zozoo.net/mq/public"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "route-exchange"
QueueName = "gangan-queue"
route = "consumer1"
que amqp.Queue
msg <-chan amqp.Delivery
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//声明队列
que, err = ch.QueueDeclare(QueueName, true, false, false, false, nil)
if err != nil {
fmt.Println("声明队列失败失败,err:", err.Error())
return
}
//声明队列
err = ch.QueueBind(QueueName, route, ExchangeName, false, nil)
if err != nil {
fmt.Println("绑定队列失败,err:", err.Error())
return
}
//消费消息
msg, err = ch.Consume(que.Name, "", true, false, false, false, nil)
if err != nil {
fmt.Println("消费消息失败,err:", err.Error())
return
}
for content := range msg {
fmt.Println("consumer1消费:", string(content.Body))
}
}
和消费者1代码一样,将
route = "consumer1"
换成route = "consumer2"
就可以了
package main
import (
"fmt"
"github.com/streadway/amqp"
"strconv"
"test.zozoo.net/mq/public"
"time"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "fanout-exchange"
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//绑定交换机
err = ch.ExchangeDeclare(
ExchangeName,
"fanout",
true,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println("绑定交换机失败,err:",err.Error())
return
}
//产生消息
for i := 0; i < 100; i++ {
msg := "第" + strconv.Itoa(i) + "条消息"
ch.Publish(
ExchangeName,
"",
false, //为true时,exchange找不到符合条件的queue,消息会返回给生产者;false时直接扔掉
false, //为true时,当queue上没有消费者时消息不会放入到队列中
amqp.Publishing{
ContentType: "text/plain", //消息类型
Body: []byte(msg), //消息内容
},
)
time.Sleep(time.Second*1)
}
fmt.Println("消息投递成功")
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"test.zozoo.net/mq/public"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "fanout-exchange"
QueueName = "fanout-queue1"
que amqp.Queue
msg <-chan amqp.Delivery
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//申明队列
que, err = ch.QueueDeclare(
QueueName,
true,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println("申明队列失败,err:", err.Error())
return
}
//将队列绑定在交换机上
err = ch.QueueBind(que.Name, "", ExchangeName, false, nil)
if err != nil {
fmt.Println("绑定交换机失败,err:", err.Error())
return
}
msg, err = ch.Consume(que.Name, "", true, false, false, false, nil)
if err != nil {
fmt.Println("消费消息失败失败,err:", err.Error())
return
}
for content := range msg {
fmt.Println("client 1 获取到消息:", string(content.Body))
}
}
和消费者1代码一样,只需要把
QueueName = "fanout-queue1"
换成QueueName = "fanout-queue2"
就可以了,这样两个消费者就能同时接收到一样的消息了
package main
import (
"fmt"
"github.com/streadway/amqp"
"strconv"
"test.zozoo.net/mq/public"
"time"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "topic-exchange"
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//声明囧还击
err = ch.ExchangeDeclare(ExchangeName, "topic", true, false, false, false, nil)
if err != nil {
fmt.Println("声明交换机失败,err:", err.Error())
return
}
//发送消息
for i := 0; i < 100; i++ {
var route = "client1.zozoo"
if i%2 == 1 {
route = "client2.zozoo"
}
msg := "第" + strconv.Itoa(i) + "条消息"
ch.Publish(ExchangeName, route, false, false, amqp.Publishing{
ContentType: "text/plain", //消息类型
Body: []byte(msg), //消息内容
})
time.Sleep(time.Second * 1)
}
fmt.Println("发送成功")
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"test.zozoo.net/mq/public"
)
func main() {
var (
ch *amqp.Channel
err error
ExchangeName = "topic-exchange"
QueueName = "tt-topic"
route = "consumer1.*"//*代表一个单词,#可以代替零个或多个单词
que amqp.Queue
msg <-chan amqp.Delivery
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//声明队列
que, err = ch.QueueDeclare(QueueName, true, false, false, false, nil)
if err != nil {
fmt.Println("声明队列失败失败,err:", err.Error())
return
}
//绑定队列
err = ch.QueueBind(que.Name, route, ExchangeName, false, nil)
if err != nil {
fmt.Println("绑定队列失败失败,err:", err.Error())
return
}
//消费消息
msg, err = ch.Consume(que.Name, "", true, false, false, false, nil)
if err != nil {
fmt.Println("消费消息失败,err:", err.Error())
return
}
for content := range msg {
fmt.Println("consumer1消费:", string(content.Body))
}
}
和消费者1代码一样,只需要修改
route = "consumer1.*"
和QueueName
就可以;注意模式简单理解就是正则匹配路由key,找到符合规则的路由发送消息
package main
import (
"fmt"
"github.com/streadway/amqp"
"strconv"
"test.zozoo.net/mq/public"
"time"
)
//工作模式模式生产者
func main() {
var (
err error
ch *amqp.Channel
que amqp.Queue
)
//获取mq连接信道
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取信道失败:", err.Error())
return
}
//声明一个死信队列交换机
err = ch.ExchangeDeclare("delay-exchange", "direct", true, false, false, false, nil)
if err != nil {
fmt.Println("创建死信交换机失败失败:", err.Error())
return
}
//声明一个死信队列
que, err = ch.QueueDeclare(
"delay-queue", //队列名称
true, //是否持久化
false, //是否自动删除
false, //是否具有排他性(队列只能被一个消费者使用,并且消费者断开连接时队列就会被删除)
false, //是否不用等待服务器确认就开始消费消息
amqp.Table{
//消息到期后将消息发送至delay-exchange交换机
"x-dead-letter-exchange": "delay-exchange",
},
)
if err != nil {
fmt.Println("创建队列失败:", err.Error())
return
}
for i:=0;i<100;i++ {
body := "延时队列"+strconv.Itoa(i)
err = ch.Publish(
"",
que.Name,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(body),
Expiration: "10000", //设置消息延时时间
},
)
if err != nil {
fmt.Println("发送消息失败,err:", err)
}
}
fmt.Println("success", time.Now())
}
package main
import (
"fmt"
"github.com/streadway/amqp"
"test.zozoo.net/mq/public"
"time"
)
func main() {
var (
ch *amqp.Channel
err error
que amqp.Queue
msg <-chan amqp.Delivery
)
ch, err = public.GetMqInstance()
if err != nil {
fmt.Println("获取连接管道失败")
return
}
//声明一个获取死信消息的队列
que, err = ch.QueueDeclare("consumer-queue", true, false, false, false, nil)
if err != nil {
fmt.Println("申明队列失败,err:", err.Error())
return
}
//将队列绑定死信交换机上,注意此处的key为产生消息的key
err = ch.QueueBind(que.Name, "delay-queue", "delay-exchange", false, nil)
if err != nil {
fmt.Println("绑定交换机失败,err:", err.Error())
return
}
msg, err = ch.Consume(que.Name, "", true, false, false, false, nil)
if err != nil {
fmt.Println("消费消息失败,err:", err.Error())
return
}
fmt.Println("消费者启动成功")
for content := range msg {
fmt.Println("client2",string(content.Body), time.Now())
}
}