msgChan, err := ch.Consume(
q.Name, // queue
"", // consumer
false, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
当auto-ack
结果为true
时,需要进行手动确认(ack)或者重试(nack)
func (d Delivery) Ack(multiple bool)
当将 multiple
参数设置为 true
时,表示要确认当前消费者标签(consumer tag)下所有未被确认的消息,即向 RabbitMQ 确认该消费者标签接收到但尚未被确认的所有消息。如果将 multiple
参数设置为 false
,则只确认当前消息一条。
因此,multiple
参数是针对某个消费者标签的,而非全局的。如果有多个消费者标签同时存在,那么分别调用它们的 Ack
方法时需要指定相应的消费者标签和 multiple
参数。
需要注意的是,使用 multiple
参数确认多条消息时,要确保这些消息都已经被正确处理。在手动确认模式下,如果存在尚未被确认的消息,RabbitMQ 就会将其重新投递到队列中,由其他消费者重新处理。如果应用程序错误地将尚未被正确处理的消息标记为“已确认”,可能会导致消息丢失或重复处理等问题。
func (d Delivery) Nack(multiple, requeue bool) error
channel.Nack
(Negative Acknowledgement)方法用于将当前正在处理的消息标记为“未确认(Unacknowledged)”,并在需要时将其重新投递到队列上。与 channel.Ack
不同的是,channel.Nack
方法可以设置 multiple
和 requeue
两个参数。
multiple
表示是否将当前消息之前的所有未确认消息都标记为“未确认”。如果将multiple
参数设置为true
,那么当前消息之前的所有未确认消息都会被标记为“未确认”并重新投递到队列的头部。否则,只有当前消息会被标记为“未确认”。requeue
表示当消息被重新投递到队列上时,是否将其重新放回到队列的头部。如果将requeue
参数设置为true
,那么消息会被重新放回到队列的头部,等待下一个消费者重新接收它。否则,消息会被直接丢弃。
通常情况下,我们使用 channel.Nack
方法将消息标记为“未确认”时,需要将 requeue
参数设置为 true
,以便重新投递该消息。这样做可以实现消息的“失败重试(Failed Retry)”机制。当消费者无法处理某个消息时,可以调用 channel.Nack
方法将该消息重新投递到队列的头部,并在一段时间后再次接收到该消息,以尝试重新处理。如果消息经过多次重新投递后仍然无法被成功处理,就会被认为是“死信消息(Dead Letter Message)”,并被发送到死信队列中。
需要注意的是,如果使用了手动确认模式,那么在重新投递消息之前,需要先调用 channel.Ack
或 channel.Reject
方法来确认或拒绝当前正在处理的消息。如果不进行确认或拒绝操作,消息可能会被重新投递到其他消费者或者死信队列中。
在 RabbitMQ 中,x-message-ttl
参数可以在声明队列、发布消息和订阅消息时进行设置,具有不同的含义和用途。下面分别介绍它们的作用:
- 声明队列时设置
x-message-ttl
在声明队列时,可以通过 arguments
参数设置 x-message-ttl
,以指定该队列中消息的存活时间。这意味着,如果一个消息在该队列中等待超过指定的时间,RabbitMQ 将自动将其删除。这对于在队列中积累大量未处理消息的场景非常有用,可以避免队列因消息堆积而被过度填满,进而影响整个系统的稳定性。
- 发布消息时设置
expiration
当您通过 AMQP 协议发布一条消息时,可以设置 expiration
字段,以指定该消息的存活时间。与队列的 x-message-ttl
类似,如果一条消息在队列中等待的时间超过指定的时间,RabbitMQ 将自动将其删除。这也可以防止未处理的消息在队列中积累过多,从而导致系统性能下降。
- 订阅消息时设置
x-message-ttl
在订阅消息时,可以通过 arguments
参数设置 x-message-ttl
,以指定在消费者从队列中接收到消息后,如果该消息在消费者队列中等待超过指定的时间,则自动将其删除。这对于需要立即处理消息的场景非常有用,可以确保消息不会在队列中长时间等待而不被及时处理。
需要注意的是,当同时设置了队列的 x-message-ttl
和消息的 expiration
参数时,消息的 expiration
参数会优先于队列的 x-message-ttl
参数。也就是说,如果消息的 expiration
时间比队列的 x-message-ttl
时间更短,那么消息将在消息的 expiration
时间到达之前被删除。如果消息的 expiration
时间比队列的 x-message-ttl
时间更长,那么消息将在队列的 x-message-ttl
时间到达之前被删除。