走近科学

tien的随笔

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

参考了:https://www.cnblogs.com/mfrank/p/11260355.html#autoid-0-8-0

demo:

利用的是RabbitMQ中的TTL(Time To Live)特性

package new_rabbitmq

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

var (
	dm  *RabbitMQ
	dl  *RabbitMQ
	err error
	url = "amqp://guest:guest@localhost:5672/?heartbeat=5"
)

// 获取rabbitmq连接
type RabbitMQ struct {
	conn    *amqp.Connection
	channel *amqp.Channel
	//队列名称
	QueueName string
	//交换机
	Exchange string
	//key
	key string
	//连接信息
	Url string
}

//创建RabbitMQ结构体实例
func NewRabbitMQ(url, queueName, exchange, key string) (*RabbitMQ, error) {
	rabbitmq := &RabbitMQ{QueueName: queueName, Exchange: exchange, key: key, Url: url}
	var err error
	//创建RabbitMQ连接
	rabbitmq.conn, err = amqp.Dial(rabbitmq.Url)
	//rabbitmq.failOnErr(err, "创建连接错误!")
	if err != nil {
		return nil, err
	}

	rabbitmq.channel, err = rabbitmq.conn.Channel()
	if err != nil {
		return nil, err
	}
	return rabbitmq, nil
}
// new一个延迟队列 绑定交换机和queue
func NewDelayMq() *RabbitMQ {

	dm, err = NewRabbitMQ(url, "delay_queue", "delay_exchange", "delay_key")
	if err != nil {
		fmt.Println("connect err:" + err.Error())
	}
	dm.SetExchange()
	dm.SetAndBindQueue(map[string]interface{}{
		"x-message-ttl":             10000, // 10s超时
		"x-dead-letter-exchange":    "dead_letter_exchange", // 指定超时时发送到哪个死信交换机
		"x-dead-letter-routing-key": "dead_letter_key", // 哪个死信队列负责处理
	})
	return dm
}
// new死信队列 绑定交换机和queue
func NewDeadLetterMq() *RabbitMQ {
	dl, err = NewRabbitMQ(url, "dead_letter_queue", "dead_letter_exchange", "dead_letter_key")
	if err != nil {
		fmt.Println("connect err:" + err.Error())
	}
	dl.SetExchange()
	dl.SetAndBindQueue(nil)

	return dl
}
// 延时队列推消息
func DelayPublish() {
	dm.DelayPublish("test delay1")
	dm.DelayPublish("test delay2")
}
// 死信消费
func DeadLetterConsume() {
	dl.DeadLetterConsume()
}

func (r *RabbitMQ) SetExchange() {
	err := r.channel.ExchangeDeclare(r.Exchange, "direct",
		true,
		false,
		false,
		false,
		nil)

	if err != nil {
		fmt.Println("exchange declare err" + err.Error())
	}
}

func (r *RabbitMQ) SetAndBindQueue(args amqp.Table) {
	_, err := r.channel.QueueDeclare(r.QueueName, true,
		false,
		false,
		false,
		args)

	if err != nil {
		fmt.Println("queue declare err" + err.Error())
	}

	err = r.channel.QueueBind(r.QueueName, r.key, r.Exchange, false, nil)
	if err != nil {
		fmt.Println("queue bind err" + err.Error())
	}
}

func (r *RabbitMQ) DelayPublish(msgStr string) {
	msg := amqp.Publishing{
		DeliveryMode: amqp.Persistent,
		Timestamp:    time.Now(),
		ContentType:  "text/plain",
		Body:         []byte(msgStr),
	}
	err := r.channel.Publish(r.Exchange, r.key, false, false, msg)
	if err != nil {
		fmt.Println("DelayPublish err" + err.Error())
	}
	fmt.Println("delay queue push msg: " + msgStr)
}

func (r *RabbitMQ) DeadLetterConsume() {
	_ = r.channel.Qos(1, 0, false)
	msgChan, err := r.channel.Consume(r.QueueName, r.key,
		false,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		fmt.Println("dead consume err:" + err.Error())
	}

	for delivery := range msgChan {
		_ = delivery.Ack(true)
		msg := string(delivery.Body)
		fmt.Println("dead letter get msg:" + msg)
	}
}

  test:

package new_rabbitmq

import "testing"

func TestDelay(t *testing.T) {
	NewDelayMq()
	NewDeadLetterMq()

	DelayPublish()
	DeadLetterConsume()
}

  

posted on 2021-11-04 14:23  _tien  阅读(153)  评论(0编辑  收藏  举报