golang + rabbitmq 死信队列

发布时间 2023-10-16 17:04:39作者: 朝阳1

生产者

package main

import (
	"fmt"
	"github.com/streadway/amqp"
	"strconv"
	"time"
)

// 启动生产者,n秒之内,如果consume没有消费,那么就会被die-死信队列消费
func main() {
	// # ========== 1.创建连接 ==========
	mq, _ := amqp.Dial("amqp://guest:guest@192.168.252.128:5672/")
	mqCh, _ := mq.Channel()
	defer mq.Close()

	// # ========== 2.设置队列(队列、交换机、绑定) ==========
	// 1:声明队列
	var err error
	//1:队列名 2:是否持久化3:是否自动删除4:是不是私有5是否等待6:额外参数 x-message-ttl: 消息过期时间,单位是毫秒。超过该时间的消息会被认为是过期消息。
	//x-dead-letter-exchange: 指定死信交换机,用于处理变成死信的消息。
	//x-dead-letter-routing-key: 指定死信的路由键,用于将死信路由到指定的队列中进行处理。
	//x-max-priority: 指定队列支持的最大消息优先级。
	_, err = mqCh.QueueDeclare("constant.NormalQueue", true, false, false, false, amqp.Table{
		"x-message-ttl":             5000,                      // 消息过期时间,毫秒
		"x-dead-letter-exchange":    "constant.DeadExchange",   // 指定死信交换机
		"x-dead-letter-routing-key": "constant.DeadRoutingKey", // 指定死信routing-key
	})
	fmt.Println(err, "创建normal队列失败")
	// 1.1 声明交换机
	//1:交换机名字2:交换机类型(直接,订阅,主题。。)3持久化 4自动删除 5
	err = mqCh.ExchangeDeclare("constant.NormalExchange", amqp.ExchangeDirect, true, false, false, false, nil)
	fmt.Println(err, "创建normal交换机失败")
	// 1.2 队列绑定(将队列、routing-key、交换机三者绑定到一起)
	err = mqCh.QueueBind("constant.NormalQueue", "constant.NormalRoutingKey", "constant.NormalExchange", false, nil)
	fmt.Println(err, "normal:队列、交换机、routing-key 绑定失败")
	// # ========== 3.设置死信队列(队列、交换机、绑定) ==========
	// 2 声明死信队列
	// args 为 nil。切记不要给死信队列设置消息过期时间,否则失效的消息进入死信队列后会再次过期。
	_, err = mqCh.QueueDeclare("constant.DeadQueue", true, false, false, false, nil)
	fmt.Println(err, "创建dead队列失败")
	// 2.1 声明交换机
	err = mqCh.ExchangeDeclare("constant.DeadExchange", amqp.ExchangeDirect, true, false, false, false, nil)
	fmt.Println(err, "创建dead队列失败")
	// 2.2 队列绑定(将队列、routing-key、交换机三者绑定到一起)
	err = mqCh.QueueBind("constant.DeadQueue", "constant.DeadRoutingKey", "constant.DeadExchange", false, nil)
	fmt.Println(err, "dead:队列、交换机、routing-key 绑定失败")
	// # ========== 4.发布消息 ==========
	message := "msg" + strconv.Itoa(int(time.Now().Unix()))
	fmt.Println(message)
	// 发布消息
	//mandatory 如果为true回根据exchange和routekey的规则,如果无法找到符合规则的队列,就会把消息返回生产者
	//immediate 如果为true,当exchange发现队列没有绑定消费者,就会把消息返回给生产者
	err = mqCh.Publish("constant.NormalExchange", "constant.NormalRoutingKey", false, false, amqp.Publishing{
		ContentType: "text/plain",
		Body:        []byte(message),
	})
	fmt.Println(err, "消息发布失败")
}

消费者

package main

import (
	"fmt"
	"github.com/streadway/amqp"
	"log"
)

func main() {
	// # ========== 1.创建连接 ==========
	mq, _ := amqp.Dial("amqp://guest:guest@192.168.252.128:5672/")
	mqCh, _ := mq.Channel()
	defer mq.Close()
	// # ========== 2.消费消息 ==========
	msgsCh, err := mqCh.Consume("constant.NormalQueue", "", false, false, false, false, nil)
	fmt.Println(err, "消费normal队列失败")
	forever := make(chan bool)
	go func() {
		for d := range msgsCh {
			// 要实现的逻辑
			log.Printf("接收的消息: %s", d.Body)
			// 手动应答
			//d.Ack(true)
			d.Reject(true) //是否拒绝,如果拒绝的话,n秒之后,就会被死信消费,或者直接不消费
		}
	}()
	log.Printf("[*] Waiting for message, To exit press CTRL+C")
	<-forever
}

死信消费者

package main

import (
	"fmt"
	"github.com/streadway/amqp"
	"log"
)

func main() {
	// # ========== 1.创建连接 ==========
	mq, _ := amqp.Dial("amqp://guest:guest@192.168.252.128:5672/")
	mqCh, _ := mq.Channel()
	defer mq.Close()
	// # ========== 2.消费死信消息 ==========
	msgsCh, err := mqCh.Consume("constant.DeadQueue", "", false, false, false, false, nil)
	fmt.Println(err, "消费dead队列失败")
	forever := make(chan bool)
	go func() {
		for d := range msgsCh {
			// 要实现的逻辑
			log.Printf("接收的消息: %s", d.Body)
			// 手动应答
			d.Ack(true)
		}
	}()
	log.Printf("[*] Waiting for message, To exit press CTRL+C")
	<-forever
}