Go RabbitMQ dead letter message queue (II)

The principle:

   /**

 (1) Create a normal queue Q1, object of business logic, such as sending messages, orders, and switches corresponding to the key bindings for the E1 and, respectively Bingkey1

 (2) create a delay message queue Q2, queue delay time is set to 10s, corresponding to the switches and keys are bound E2 and Bingkey2; and when creating the queue, the queue timeout setting (a) time (b) routing the time-out after the jump and E1 binding Bingkey1, i.e. after a timeout jump queues Q1

 (3) the first message sent to the queue Q2, queue and wait for timeout, execution logic

 

 

 

 

 * The main test a dead letter queue, main function of delay consumption, the principle is the first message sent to the normal queue,

 * There are the normal queue timeout, when the time is reached automatically sent to the dead letter queue, and then by the consumer to consume the dead letter queue messages. * /

 

Delay queue scenarios

1、未支付订单定时取消
2、定时清理缓存对象、空闲连接等
3、下单成功后30分钟内,按不同时间间隔发送通知等(1min、3min、10min发一次)


1, set an expiration time queue

$this->channel->queue_declare(
            $this->retry_queue(),
            false,
            true,
            false, false, false, new AMQPTable( [ # 不设置x-dead-letter-routing-key,使用原先的routing_key,10s过期后自动重回原先的队列里面,那x-dead-letter-exchange交换机就需绑定原先队列 'x-dead-letter-exchange' => $this->retry_exchange(), # 10s 'x-message-ttl' => 10000, ] ) );

All messages are pushed to the queue (no TTL), will expire after 10s, according to the original routing_key, into the specified Exchange, and further proceeds to a specified queue.

 

2, set the message expiration time

$message = new AMQPMessage(
    'msg',
    array(
        # 消息持久化
        'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSITENT, # ttl过期时间 'expiration' => 50000, ) );

Each message are set to expire the same time, the message will be invalid after the expiration.

3, and set an expiration time of the queue, the message

If both, the message expiration time may depend on a smaller value, such as queue 'x-message-ttl' is set to 10s, the message 'expiration' is set to 50s, then the message will fail after 10s.

 

4, subsequent

Ttl queue provided alone, or just set the same message expiration time, dead letter queue is operable under normal condition. But set a different message expiration time, it may not work properly dead letter queue up.

Queue no ttl

$this->channel->queue_declare(
            $this->retry_queue(),
            false,
            true,
            false, false, false, new AMQPTable( [ # 不设置x-dead-letter-routing-key,使用原先的routing_key,10s过期后自动重回原先的队列里面,那x-dead-letter-exchange交换机就需绑定原先队列 'x-dead-letter-exchange' => $this->retry_exchange(), ] ) );

The first message is set 500s expired, pushing forward queue

 

 

The first message is set 500s expired, pushing forward queue

$message = new AMQPMessage(
    'msg',
    array(
        # 消息持久化
        'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSITENT, # ttl过期时间 'expiration' => 500000, ) );

The second message is provided 5s expire after advancing queue

$message = new AMQPMessage(
    'msg',
    array(
        # 消息持久化
        'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSITENT, # ttl过期时间 'expiration' => 5000, ) );

The results showed that, after 5s, there are two queue message. Description The second message did not "really expired." The reason is at the head of the queue message has not expired. And rabbitmq the dead letter queue is implemented based on message header.

5 Conclusion

When the first message queue MQ check and found it has not expired, it will not continue after the check message. Even after the message has expired, will not because the head of the queue and can not transfer to another queue, which is determined by the characteristics of the MQ queue. You can not go consumption in the middle of a message queue, the queue must FIFO.

For setting queue attributes TTL method, once the message is expired, will be erased from the queue, provided the message header properties, even if the message is expired, is not immediately erased from the queue, because every message is about to expire decision prior to delivery to the consumer, why do not coincide get treatment? Since the first method, the message queue has expired certainly head of the queue, RabbitMQ as long as regular first team from start to scan for expired messages, while the second method, the different expiration time of each message, if to delete all expired messages, is bound to scan the entire queue, so better and so this news is about to expire and then determine whether the time of consumption, if expired, and then delete it.

The official narrative

"Only when expired messages reach the head of a queue will they actually be discarded (or dead-lettered)." 只有当过期的消息到了队列的顶端(队首),才会被真正的丢弃或者进入死信队列。

 

 

 

Guess you like

Origin www.cnblogs.com/fengchuiyizh/p/12297830.html