What is a delay queue:
delay queue, first of all, it is a queue. Queue means that the internal elements are orderly, the outgoing and incoming elements are directional, and the elements enter from one end and take out from the other end.
secondly, the most important feature of delay queue is its delay attribute. Unlike ordinary queue, elements in ordinary queue always wait to be taken out and processed earlier, while elements in delay queue want to be taken out and processed at a specified time. Therefore, elements in delay queue have time attribute, Generally speaking, it is a message or task that needs to be processed.
in short, a delay queue is a queue used to store elements that need to be processed at a specified time.
Delay queue usage scenario:
so when do you need to use delay queues? Consider the following scenario:
if the order is not paid within ten minutes, it will be automatically cancelled.
if the newly created store has not uploaded goods within ten days, it will automatically send a message reminder.
if the bill is not paid within one week, it will be settled automatically.
after the user is registered successfully, if he does not log in within three days, he will be prompted by SMS.
the user initiates a refund. If it is not handled within three days, notify the relevant operation personnel.
after the scheduled meeting, all participants shall be notified to attend the meeting ten minutes before the scheduled time point.
Implementation of delay queue:
1. Using TTL + dead letter queue
the producer produces a delayed message. According to the required delay time, different routingkeys are used to route the message to different delay queues. Each queue has different TTL attributes and is bound to the same dead letter switch. After the message expires, it will be routed to different dead letter queues according to different routingkeys, Consumers only need to listen to the corresponding dead letter queue for processing.
the disadvantages of this method are that it can not be universal. Every time a new delayed task is carried out, it is troublesome to implement an implemented TTL + dead letter queue;
2. Using RabbitMQ plug-in
just install a plug-in: https://www.rabbitmq.com/community-plugins.html , Download rabbitmq_delayed_message_exchange plug-in, and then unzip and place it in the plug-in directory of RabbitMQ.
view the release history and download 3.8 0 version
3. RabbitMQ container configuration plug-in:
3.1. Enter the container to view the MQ plug-in Directory: plugins/
[root@VM-0-12-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@VM-0-12-centos ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 74f929cfb3c9 rabbitmq:3-management "docker-entrypoint..." 4 weeks ago Exited (0) 18 minutes ago rabbitMQ [root@VM-0-12-centos ~]# docker start 74f929cfb3c9 74f929cfb3c9 [root@VM-0-12-centos ~]# docker exec -it 74f929cfb3c9 bash root@74f929cfb3c9:/# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt opt plugins proc root run sbin srv sys tmp usr var root@74f929cfb3c9:/# cd plugins root@74f929cfb3c9:/plugins# ls README cuttlefish-3.0.0.ez ra-1.1.8.ez rabbitmq_consistent_hash_exchange-3.8.18.ez rabbitmq_peer_discovery_consul-3.8.18.ez rabbitmq_stomp-3.8.18.ez recon-2.5.1.ez accept-0.3.5.ez eetcd-0.3.3.ez rabbit-3.8.18.ez rabbitmq_event_exchange-3.8.18.ez rabbitmq_peer_discovery_etcd-3.8.18.ez rabbitmq_top-3.8.18.ez stdout_formatter-0.2.4.ez amqp10_client-3.8.18.ez gen_batch_server-0.8.4.ez rabbit_common-3.8.18.ez rabbitmq_federation-3.8.18.ez rabbitmq_peer_discovery_k8s-3.8.18.ez rabbitmq_tracing-3.8.18.ez syslog-3.4.5.ez amqp10_common-3.8.18.ez goldrush-0.1.9.ez rabbitmq_amqp1_0-3.8.18.ez rabbitmq_federation_management-3.8.18.ez rabbitmq_prelaunch-3.8.18.ez rabbitmq_trust_store-3.8.18.ez sysmon_handler-1.3.0.ez amqp_client-3.8.18.ez gun-1.3.3.ez rabbitmq_auth_backend_cache-3.8.18.ez rabbitmq_jms_topic_exchange-3.8.18.ez rabbitmq_prometheus-3.8.18.ez rabbitmq_web_dispatch-3.8.18.ez aten-0.5.5.ez jose-1.11.1.ez rabbitmq_auth_backend_http-3.8.18.ez rabbitmq_management-3.8.18.ez rabbitmq_random_exchange-3.8.18.ez rabbitmq_web_mqtt-3.8.18.ez base64url-1.0.1.ez jsx-3.1.0.ez rabbitmq_auth_backend_ldap-3.8.18.ez rabbitmq_management_agent-3.8.18.ez rabbitmq_recent_history_exchange-3.8.18.ez rabbitmq_web_mqtt_examples-3.8.18.ez cowboy-2.8.0.ez lager-3.9.2.ez rabbitmq_auth_backend_oauth2-3.8.18.ez rabbitmq_mqtt-3.8.18.ez rabbitmq_sharding-3.8.18.ez rabbitmq_web_stomp-3.8.18.ez cowlib-2.9.1.ez observer_cli-1.6.2.ez rabbitmq_auth_mechanism_ssl-3.8.18.ez rabbitmq_peer_discovery_aws-3.8.18.ez rabbitmq_shovel-3.8.18.ez rabbitmq_web_stomp_examples-3.8.18.ez credentials_obfuscation-2.4.0.ez prometheus-4.6.0.ez rabbitmq_aws-3.8.18.ez rabbitmq_peer_discovery_common-3.8.18.ez rabbitmq_shovel_management-3.8.18.ez ranch-2.0.0.ez root@74f929cfb3c9:/plugins#
3.2 rabbitmq to be downloaded_ delayed_ message_ Put the exchange plug-in under the / home/docker/rabbitmq / path of the server
3.3. Rabbitmq_ delayed_ message_ Copy the exchange plug-in to the plugins directory of the container and confirm
command: docker cp local file path container ID or full name: container path
[root@VM-0-12-centos /]# docker cp home/docker/rabbitmq/rabbitmq_delayed_message_exchange-3.8.0.ez 74f929cfb3c9:plugins/ [root@VM-0-12-centos /]# docker exec -it 74f929cfb3c9 bash root@74f929cfb3c9:/# cd plugins root@74f929cfb3c9:/plugins# ls README cuttlefish-3.0.0.ez ra-1.1.8.ez rabbitmq_consistent_hash_exchange-3.8.18.ez rabbitmq_peer_discovery_common-3.8.18.ez rabbitmq_shovel_management-3.8.18.ez ranch-2.0.0.ez accept-0.3.5.ez eetcd-0.3.3.ez rabbit-3.8.18.ez rabbitmq_delayed_message_exchange-3.8.0.ez rabbitmq_peer_discovery_consul-3.8.18.ez rabbitmq_stomp-3.8.18.ez recon-2.5.1.ez amqp10_client-3.8.18.ez gen_batch_server-0.8.4.ez rabbit_common-3.8.18.ez rabbitmq_event_exchange-3.8.18.ez rabbitmq_peer_discovery_etcd-3.8.18.ez rabbitmq_top-3.8.18.ez stdout_formatter-0.2.4.ez amqp10_common-3.8.18.ez goldrush-0.1.9.ez rabbitmq_amqp1_0-3.8.18.ez rabbitmq_federation-3.8.18.ez rabbitmq_peer_discovery_k8s-3.8.18.ez rabbitmq_tracing-3.8.18.ez syslog-3.4.5.ez amqp_client-3.8.18.ez gun-1.3.3.ez rabbitmq_auth_backend_cache-3.8.18.ez rabbitmq_federation_management-3.8.18.ez rabbitmq_prelaunch-3.8.18.ez rabbitmq_trust_store-3.8.18.ez sysmon_handler-1.3.0.ez aten-0.5.5.ez jose-1.11.1.ez rabbitmq_auth_backend_http-3.8.18.ez rabbitmq_jms_topic_exchange-3.8.18.ez rabbitmq_prometheus-3.8.18.ez rabbitmq_web_dispatch-3.8.18.ez base64url-1.0.1.ez jsx-3.1.0.ez rabbitmq_auth_backend_ldap-3.8.18.ez rabbitmq_management-3.8.18.ez rabbitmq_random_exchange-3.8.18.ez rabbitmq_web_mqtt-3.8.18.ez cowboy-2.8.0.ez lager-3.9.2.ez rabbitmq_auth_backend_oauth2-3.8.18.ez rabbitmq_management_agent-3.8.18.ez rabbitmq_recent_history_exchange-3.8.18.ez rabbitmq_web_mqtt_examples-3.8.18.ez cowlib-2.9.1.ez observer_cli-1.6.2.ez rabbitmq_auth_mechanism_ssl-3.8.18.ez rabbitmq_mqtt-3.8.18.ez rabbitmq_sharding-3.8.18.ez rabbitmq_web_stomp-3.8.18.ez credentials_obfuscation-2.4.0.ez prometheus-4.6.0.ez rabbitmq_aws-3.8.18.ez rabbitmq_peer_discovery_aws-3.8.18.ez rabbitmq_shovel-3.8.18.ez rabbitmq_web_stomp_examples-3.8.18.ez root@74f929cfb3c9:/plugins#
3.4. Next, enter the sbin directory under the RabbitMQ installation directory, execute the following command to make the plug-in effective, and then restart RabbitMQ.
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
root@74f929cfb3c9:/plugins# cd /sbin root@74f929cfb3c9:/sbin# rabbitmq-plugins enable rabbitmq_delayed_message_exchange Enabling plugins on node rabbit@74f929cfb3c9: rabbitmq_delayed_message_exchange The following plugins have been configured: rabbitmq_delayed_message_exchange rabbitmq_management rabbitmq_management_agent rabbitmq_prometheus rabbitmq_web_dispatch Applying plugin configuration to rabbit@74f929cfb3c9... The following plugins have been enabled: rabbitmq_delayed_message_exchange started 1 plugins. root@74f929cfb3c9:/sbin#
RabbitMqConfig configuration:
1. Configure delay queue
/** * delayedDirect Switch name */ public static final String DELAYED_DIRECT_EXCHANGE="delayedDirectExchange"; /** * delayedDirect Queue name */ public static final String DELAYED_DIRECT_QUEUE="delayedDirectQueue"; /** * delayedDirec The key that the switch binds to the delayedDirec queue */ public static final String DELAYED_DIRECT_ROUTINGKEY="delayedDirectRouingkey"; /** * Define a delayedDirect switch * Custom switch * @return */ @Bean public CustomExchange delayedDirectExchange(){ /** * CustomExchange(String name, String type, boolean durable, boolean autoDelete, Map<String, Object> arguments) * Description of construction parameters: * name: Switch name, type: user-defined type (the plug-in provides a type called x-delayed-message), durable persistence, autoDelete automatic deletion, and arguments are used to pass other attribute configurations */ Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange(DELAYED_DIRECT_EXCHANGE,"x-delayed-message", true, false, args); } /** * Define a delayedDirect queue * @return */ @Bean public Queue delayedDirectQueue(){ return new Queue(DELAYED_DIRECT_QUEUE); } /** * Define a binding rule between the delayedDirect queue and the delayedDirect switch * @return */ @Bean public Binding delayedDirectBinding(){ return BindingBuilder.bind(delayedDirectQueue()).to(delayedDirectExchange()).with(DELAYED_DIRECT_ROUTINGKEY).noargs(); }
2. Producer sending message method
/** * Send delayed message * @param message news * @param delayTime Delay time in milliseconds */ @Override public void sendDelayedMessage(String message, Integer delayTime) { rabbitTemplate.convertAndSend(RabbitMqConfig.DELAYED_DIRECT_EXCHANGE,RabbitMqConfig.DELAYED_DIRECT_ROUTINGKEY,message,messagePostProcessor->{ messagePostProcessor.getMessageProperties().setDelay(delayTime); return messagePostProcessor; }); }
3. Method for consumers to receive messages
@Override @RabbitListener(queues = {RabbitMqConfig.DELAYED_DIRECT_QUEUE}) //listen queue public void receiveMessage2(String message) { System.out.println("Receive delay message:"+message +" : "+ new Date().toString()); }
4. Send a message test and close the manual ACK
package com.java996.producer; import com.java996.producer.Service.RabbitMqService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class ProducerApp { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ProducerApp.class,args); RabbitMqService rabbitMqService = (RabbitMqService) context.getBean("RabbitMqService"); rabbitMqService.sendDelayedMessage("Test delay message: 10 seconds",10000); rabbitMqService.sendDelayedMessage("Test delay message: 20 seconds",20000); } }
5. Test result: the consumption time interval between two messages is 10 seconds