GoLang RabbitMQ TTL与死信队列以及延迟队列详细讲解

 更新时间:2022年12月15日 14:36:12   作者:Onemorelight95  
这篇文章主要介绍了GoLang RabbitMQ TTL与死信队列以及延迟队列,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

TTL

TTL 全称 Time To Live(存活时间/过期时间)。当消息到达存活时间后,还没有被消费,就会被自动清除。RabbitMQ可以设置两种过期时间:

  • 对消息设置过期时间。
  • 对整个队列(Queue)设置过期时间。

如何设置

  • 设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
  • 设置消息过期时间使用参数:expiration,单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。

如果两者都设置了过期时间,以时间短的为准。

在streadway/amqp库提供的API中设置TTL

设置队列过期时间:

QueueDeclare函数的最后一个参数是一个amqp.Table类型,它的声明是这样的: type Table map[string]interface{},其实是一个可以用于设置队列属性的map。

// 设置Queue ttl为5s
args := amqp.Table{"x-message-ttl": 5000}
q, e := ch.QueueDeclare(
		name,  //队列名
		false, 
		true, 
		false, 
		false,
		args,   //设置Queue ttl为5s
	)

设置消息过期时间:

e = q.channel.Publish(
		"",    
		queue, 
		false, 
		false, 
		amqp.Publishing{
			// 设置当前发送消息的过期时间为3s
			Expiration: "3000",
			ReplyTo:    q.Name,
			Body:       []byte(str),
})

死信队列

当一个队列中存在死信时,RabbitMQ会把消息发送给DLX(死信交换机),进而被路由到另一个队列中,这个队列就叫做死信队列。

死信就是指没有被消费者消费成功的消息,一条消息变成死信有三种情况:

  • 如果给消息队列设置了最大容量x-max-length,队列已经满了,后续再进来的消息会溢出,无法被队列接收就会变成死信。
  • 消息接收时被拒绝会变成死信,例如调用Reject()函数,并设置requeuefalse
  • 如果给消息队列设置了消息的过期时间x-message-ttl,或者发送消息时设置了当前消息的过期时间,当消息在队列中的存活时间大于过期时间时,就会变成死信。

如何将死信发送给DLX

为队列设置参数即可,将要发送死信的队列配置以下两个参数:

x-dead-letter-exchange: [DLX的名字]
x-dead-letter-routing-key: [DLX的routing key]

下面是死信队列的工作流程:

延迟队列

延时队列就是用来存放需要在指定时间被处理的元素的队列,通常可以用来处理一些具有过期性操作的业务。

比如十分钟内未支付则取消订单,原先这个功能我们可以使用定时器来实现,即每隔一段时间去数据库对比未支付订单的当前时间与订单创建时间。但是定时器的时长难以确定,太长会导致订单失效时间出现误差,太短则会增大数据库压力。

实现

在RabbitMQ中没有提供延迟队列的功能,但是我们可以使用:TTL+死信队列组合的方式来实现延迟队列的效果。

下面是实现延迟队列的流程图:

Go实现延迟队列

创建一个死信交换机

再创建一个死信队列

将死信队列绑定至死信交换机

创建一个正常队列,并指定消息过期后被发往的死信交换机

生产者

func main() {
	conn, _ := amqp.Dial("amqp://guest:guest@35.76.111.125:5672/")
	ch, _ := conn.Channel()
	body := "This is a delayed message, created at " + time.Now().Format("2006-01-02 15:04:05")
	fmt.Println(body)
	// 发送消息到queue.normal队列中
	ch.Publish("", "queue.normal", false, false, amqp.Publishing{
		Body:       []byte(body),
		Expiration: "10000", // 设置TTL为10秒
	})
	defer conn.Close()
	defer ch.Close()
}

消费者

func main() {
	conn, _ := amqp.Dial("amqp://guest:guest@35.76.111.125:5672/")
	ch, _ := conn.Channel()
	//监听queue.dlx队列
	msgs, _ := ch.Consume(
		"queue.dlx",
		"",
		true,
		false,
		false,
		false,
		nil,
	)
	for d := range msgs {
		fmt.Printf("receive: %s\n", d.Body) // 收到消息,业务处理
	}
}

流程说明

生产者生产一条消息,然后指定消息的TTL为10s,接着将消息发给普通队列,消息在普通队列中过期后被发往死信交换机,死信交换机将这条消息路由给延迟队列。消费者一直在监听到延迟队列中的死信后,开始消费。

到此这篇关于GoLang RabbitMQ TTL与死信队列以及延迟队列详细讲解的文章就介绍到这了,更多相关GoLang RabbitMQ内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang中panic与recover的区别

    Golang中panic与recover的区别

    这篇文章主要介绍了Golang中panic与recover的区别,文章基于Golang的基础内容展开panic与recover的区别介绍,需要的小伙伴可以参考一下
    2022-06-06
  • 浅析Go语言如何在select语句中实现优先级

    浅析Go语言如何在select语句中实现优先级

    这篇文章主要为大家详细介绍了Go语言如何在select语句中实现优先级,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • Go语言中循环语句使用的示例详解

    Go语言中循环语句使用的示例详解

    在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。本文将通过示例详细为大家讲讲Go语言中的循环语句,需要的可以参考一下
    2022-04-04
  • Go语言定时任务的实现示例

    Go语言定时任务的实现示例

    本文主要介绍了Go语言定时任务的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • 解决go在函数退出后子协程的退出问题

    解决go在函数退出后子协程的退出问题

    这篇文章主要介绍了解决go在函数退出后子协程的退出问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go语言resty http包调用jenkins api实例

    Go语言resty http包调用jenkins api实例

    这篇文章主要为大家介绍了Go语言resty http包调用jenkins api实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Golang中make与new使用区别小结

    Golang中make与new使用区别小结

    Go语言中new和make是内建的两个函数,主要用来创建分配类型内存,本文主要给大家介绍了Go语言中函数new与make的使用和区别,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • go语言区块链实战实现简单的区块与区块链

    go语言区块链实战实现简单的区块与区块链

    这篇文章主要为大家介绍了go语言区块链的实战学习,来实现简单的区块与区块链示例过程,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • goland 导入github包报红问题解决

    goland 导入github包报红问题解决

    本文主要介绍了Go项目在GoLand中导入依赖标红问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • GO语言基础之数组

    GO语言基础之数组

    或许您是从其他语言转到GO语言这边的,那麽在其他语言的影响下您可能会不太适应GO语言的数组,因为GO语言把数组给拆分成了array,slice和map,需要的朋友可以参考下
    2015-01-01

最新评论