go rabbitmq使用实例,延时队列使用实例

前提条件,需要包含一个公告的获取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()
}

一、简单模式

  • 生产者 product.go
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("消息投递成功")
}
  • 消费者 consumer.go
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))
	}
}

二、工作模式

工作模式和简单模式一样,就是多几个消费者消费消息而已

三、路由模式

  • 生产者 produce.go
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("发送完成")
}
  • 消费者1 consumer1.go
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))
	}
}
  • 消费者2 consumer2.go

和消费者1代码一样,将route = "consumer1" 换成 route = "consumer2"就可以了

四、发布订阅模式

  • 生产者 produce.go
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("消息投递成功")
}
  • 消费者1 consumer1.go
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))
	}
}
  • 消费者2 consumer2.go

和消费者1代码一样,只需要把QueueName = "fanout-queue1" 换成 QueueName = "fanout-queue2"就可以了,这样两个消费者就能同时接收到一样的消息了

五、主题模式

  • 生产者 produce.go
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("发送成功")
}
  • 消费者1 consumer1.go
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))
	}
}
  • 消费者2 consumer2.go

和消费者1代码一样,只需要修改route = "consumer1.*"QueueName就可以;注意模式简单理解就是正则匹配路由key,找到符合规则的路由发送消息

延时队列的使用

  • 生产者 produce.go
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())
}

  • 消费者 consumer.go
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())
	}
}

你可能感兴趣的:(go,rabbitmq,golang,分布式)