RabbitMq (7) push message delay

 

Scenarios

Current common application software has delayed pushed message shadow, it has found many applications, such as:

  • Taobao seven days automatically confirm receipt. After our receipt of goods, logistics system will delay seven days after sending a message to the payment system, payment system will notify shall call businesses, this process lasted seven days is to use the delay function push messaging middleware.
  • 12306 ticket payment confirmation page. We selected tickets click OK to jump page often there will be a countdown, representing the order is not confirmed within 30 minutes, then will automatically cancel the order. In fact, the moment of ordering ticketing service system will send a message to delay ordering system, delay 30 minutes to tell the order system order backlog, if we finish the order within 30 minutes, it can be judged by the logic code ignore the message out received.

In the above two scenarios, if we use the following two conventional solutions undoubtedly greatly reduces the overall performance and throughput of the system:

  • Use redis set the expiration time to order, and finally by determining whether there redis order to decide whether the order has been completed. This solution compared to the low latency performance push message, because we know redis are stored in memory, we encountered a malicious orders or scalping will put huge pressure on memory.
  • Using traditional database polling to determine the status of an order in a database table, it will increase the number of IO, very low performance.
  • Use jvm native DelayQueue, but also memory-intensive, and there is no persistence strategy, system downtime or reboot order information will be lost.

Message delay push to achieve

Before RabbitMQ 3.6.x we generally use the dead-letter queue + TTL expiration time to achieve delay queue.

The beginning of the RabbitMQ 3.6.x, RabbitMQ official queue delay plug-ins, you can download plugins to be placed in the root directory of RabbitMQ

Resource address: https: //www.rabbitmq.com/community-plugins.html

I was here in the windows, download, unzip put such plugin, then cmd:

D:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.9\sbin>rabbitmq-plugins enable rabbitmq_delayed_message_exchange

Sample Code

  / ** 
     * Delay Queue 
     * / 
    public  static  Final String DELAY_QUEUE = "delay.queue" ; 

   @Bean 
    public Queue DelayQueue () {
         return  new new Queue (DELAY_QUEUE, to true ); 
    } 

    @Bean 
    TopicExchange delayExchange () { 
        the Map <String, Object> = Pros new new the HashMap <String, Object> ();
         // set the delay message switch supports push 
        pros.put ( "X-dELAYED-message", "Topic" ); 
        TopicExchange delayTopicExchange = new new TopicExchange ( "delayTopicExchange",true,false,pros);

        delayTopicExchange.setDelayed(true);
        return delayTopicExchange;
    }

    @Bean
    Binding bindingDelayExchange(Queue delayQueue, TopicExchange delayExchange) {
        return BindingBuilder.bind(delayQueue).to(delayExchange).with("delay.#");
    }

Producer:

 public void delaySend() throws IOException {
        User user = new User();
        user.setUserName("Sender1.....");
        user.setMobile("6666666");
        byte[] body = Base64Utils.obj2byte(user);

        Message message = new Message(body,new MessageProperties());

        //延时插件https://www.rabbitmq.com/community-plugins.html
        //然后放plugin包
        //启用插件:rabbitmq-plugins enable rabbitmq_delayed_message_exchange
        //Lambda表达式
        MessagePostProcessor messagePostProcessor = message1 -> {
            //设置消息持久化
            message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
            message.getMessageProperties().setHeader("x-delay", 10000);
            //message.getMessageProperties().setDelay(20000);
            return message;
        };

        System.out.println("发送演示消息>>>>>"+new Date());
        rabbitTemplate.convertAndSend("delayTopicExchange","delay.message",message,messagePostProcessor);
    }

rabbitTemplate usually in the default configuration in SpringBoot

Test Case:

   @Test
    public void send6() throws Exception {
        topicSender.delaySend();
    }

Run:

 

 

Consumer end (another project):

 

 /**
     * 延时Queue
     */
    public static final String DELAY_QUEUE = "delay.queue";
package com.example.demo.rabbitMq.exchange.topic;

import com.example.demo.utils.Base64Utils;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

@Component
public class TopicReceiver6 {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @RabbitListener(queues = TopicRabbitConstant.DELAY_QUEUE)
    public void process(Message message, Channel channel) throws IOException {
        try {
            System.out.println("Receiver6  : " + new Date() + ">>>>" + Base64Utils.byteToObj(message.getBody()));

        } catch (Exception e) {
            logger.error("接收失败",e);
        }
    }
}

Overall test verification

1, start the consumer side

2, the producer sends a message

result:

Producers Project Console:

Consumer side project Console:

Interval 10s

 

reference:

https://www.cnblogs.com/haixiang/p/10966985.html

Guess you like

Origin www.cnblogs.com/xiaozhuanfeng/p/10969416.html