go 调用rabbitmq 死信队列

2,340 阅读2分钟
  1. 死信队列:消息过期,消息被拒绝,队列达到最大长度,都会将消息丢失,此时可设置死信队列,将消息放入死信队列中再进行消费
  • 生产者

    package product
    
    import (
    	"fmt"
    	"github.com/streadway/amqp"
    )
    
    func ProducerDlx()  {
    	var(
    		conn *amqp.Connection
    		err error
    		ch *amqp.Channel
    	)
    	if conn, err = amqp.Dial("amqp://liulong:liulong@127.0.0.1:5672/"); err!=nil{
    		fmt.Println("amqp.Dial err :", err)
    		return
    	}
    	defer conn.Close()
    
    	if ch, err = conn.Channel(); err!=nil{
    		fmt.Println("conn.Channel err: ", err)
    		return
    	}
    
    	defer ch.Close()
    	
    
    	//声明交换器
    	if err = ch.ExchangeDeclare(
    		"long_abc",
    		amqp.ExchangeDirect,
    		true,
    		false,
    		false,
    		false,
    		nil,
    	); err!=nil{
    		fmt.Println("ch.ExchangeDeclare err: ", err)
    		return
    	}
    	
    
    	//发送消息
    	if err = ch.Publish(
    		"long_abc",
    		"zhe_mess",
    		false,
    		false,
    		amqp.Publishing{
    			Headers: amqp.Table{},
    			ContentType:"text/plain",
    			Body:[]byte("hello world dlx"),
    			DeliveryMode:amqp.Persistent,
    			Priority:0,
    		},
    	); err!=nil{
    		fmt.Println("ch.Publish err: ", err)
    		return
    	}
    }

  • 消费正常队列

    package consum
    
    import (
    	"fmt"
    	"github.com/streadway/amqp"
    	"time"
    )
    
    
    func Consumer()  {
    	var(
    		conn *amqp.Connection
    		err error
    		ch *amqp.Channel
    		queue amqp.Queue
    		dlxExchangeName string
    		delvers <- chan amqp.Delivery
    		message amqp.Delivery
    		ok bool
    	)
    	if conn, err = amqp.Dial("amqp://liulong:liulong@127.0.0.1:5672/"); err!=nil{
    		fmt.Println("amqp.Dial err :", err)
    		return
    	}
    	defer conn.Close()
    
    	if ch, err = conn.Channel(); err!=nil{
    		fmt.Println("conn.Channel err: ", err)
    		return
    	}
    
    	defer ch.Close()
    
    	//设置未确认的最大消息数
    	if err = ch.Qos(3, 0, false); err!=nil{
    		fmt.Println("ch.Qos err: ", err)
    		return
    	}
    
    	dlxExchangeName = "dlx_exchange"
    
    	//声明交换器
    	if err = ch.ExchangeDeclare(
    		"long_abc",
    		amqp.ExchangeDirect,
    		true,
    		false,
    		false,
    		false,
    		nil,
    	); err!=nil{
    		fmt.Println("ch.ExchangeDeclare err: ", err)
    		return
    	}
    
    	argsQue := make(map[string]interface{})
            //添加死信队列交换器属性
    	argsQue["x-dead-letter-exchange"] = dlxExchangeName
    	//指定死信队列的路由key,不指定使用队列路由键
    	//argsQue["x-dead-letter-routing-key"] = "zhe_mess"
    	//添加过期时间
    	argsQue["x-message-ttl"] = 6000  //单位毫秒
    	//声明队列
    	queue, err = ch.QueueDeclare("zhe_123", true, false, false, false, argsQue)
    	if err !=nil{
    		fmt.Println("ch.QueueDeclare err :", err)
    		return
    	}
    
    	//绑定交换器/队列和key
    	if err = ch.QueueBind(queue.Name, "zhe_mess", "long_abc", false, nil);err!=nil{
    		fmt.Println("ch.QueueBind err: ", err)
    		return
    	}
    	//开启推模式消费
    	delvers, err = ch.Consume(
    		queue.Name,
    		"",
    		false,
    		false,
    		false,
    		false,
    		nil,
    	)
    
    	if err!=nil{
    		fmt.Println("ch.Consume err: ", err)
    	}
    
    	//消费接收到的消息
    	for{
    		select {
    		case message, ok = <- delvers:
    			if !ok{
    				continue
    			}
    			go func() {
    				//处理消息
    				time.Sleep(time.Second*2)
    				//确认接收到的消息
    				if err = message.Ack(true); err!=nil{
    					//TODD: 获取到消息后,在过期时间内如果未进行确认,此消息就会流入到死信队列,此时进行消息确认就会报错
    					fmt.Println("d.Ack err: ", err)
    					return
    				}
    				fmt.Println("已确认", string(message.Body))
    			}()
    		case <-time.After(time.Second*1):
    
    		}
    	}
    
  • 消费死信队列

    package consum
    
    import (
    	"fmt"
    	"github.com/streadway/amqp"
    	"time"
    )
    
    func ConsumerDlx()  {
    
    	var(
    		conn *amqp.Connection
    		ch *amqp.Channel
    		queue amqp.Queue
    		err error
    		delvers <- chan amqp.Delivery
    		message amqp.Delivery
    		ok bool
    	)
    
    	//链接rbmq
    	if conn, err = amqp.Dial("amqp://liulong:liulong@52.83.64.102:5672/");err!=nil{
    		fmt.Println("amqp.Dial err: ", err)
    		return
    	}
    
    	//声明信道
    	if ch, err = conn.Channel(); err!=nil{
    		fmt.Println("conn.Channel err: ", err)
    		return
    	}
    
    
    	//声明交换机
    	if err = ch.ExchangeDeclare(
    		"dlx_exchange",
    		amqp.ExchangeFanout,   //交换机模式fanout
    		true,          //持久化
    		false,      //自动删除
    		false,        //是否是内置交互器,(只能通过交换器将消息路由到此交互器,不能通过客户端发送消息
    		false,
    		nil,
    	); err!=nil{
    		fmt.Println("ch.ExchangeDeclare: ", err)
    		return
    	}
    
    	//声明队列
    	if queue, err = ch.QueueDeclare(
    		"dlx_queue",       //队列名称
    		true,      //是否是持久化
    		false,   //是否不需要确认,自动删除消息
    		false,   //是否是排他队列
    		false,    //是否等待服务器返回ok
    		nil,
    	); err!=nil{
    		fmt.Println("ch.QueueDeclare err: ", err)
    		return
    	}
    
    
    	//将交换器和队列/路由key绑定
    	if err = ch.QueueBind(queue.Name, "", "dlx_exchange", false, nil); err!=nil{
    		fmt.Println("ch.QueueBind err: ", err)
    		return
    	}
    
    
    
    	//开启推模式消费
    	delvers, err = ch.Consume(
    		queue.Name,
    		"",
    		false,
    		false,
    		false,
    		false,
    		nil,
    	)
    
    	if err!=nil{
    		fmt.Println("ch.Consume err: ", err)
    	}
    
    	//消费接收到的消息
    	for{
    		select {
    		case message, ok = <- delvers:
    			if !ok{
    				continue
    			}
    			go func() {
    				//处理消息
    				time.Sleep(time.Second*3)
    				//确认接收到的消息
    				if err = message.Ack(true); err!=nil{
    					fmt.Println("dlx d.Ack err: ", err)
    					return
    				}
    				fmt.Println("已确认dlx", string(message.Body))
    			}()
    		case <-time.After(time.Second*1):
    
    		}
    	}
    }