Main functions of message queue: traffic peak clipping
If the order system can process 10000 orders at most, this processing capacity is more than enough to deal with the order in the normal period. In the normal period, we can return the results one second after we place the order. However, in the peak period, if 20000 orders are placed, the operating system can not handle them. Users can only be restricted from placing orders after more than 10000 orders. Using the message queue as a buffer, we can cancel this restriction and disperse the orders placed in one second into a period of time. At this time, some users may not receive the successful operation of placing an order until more than ten seconds after placing an order, but it is better than the experience of not placing an order.
Application decoupling:
Asynchronous processing:
Common message queues:
kafka: usually big data processing
RocketMQ: it's very reliable. Generally, it's at the financial level and can't be used
RabbitMQ: One of the most popular message oriented middleware. Combined with the concurrency advantages of erlang language itself, it has good performance, timeliness, microsecond level, high community activity, and convenient management interface. If your data volume is not so large, small and medium-sized companies give priority to RabbitMQ with relatively complete functions;
Four core concepts:
producer
Switch: on the one hand, it receives messages from producers, on the other hand, it pushes messages to queues. The switch must know exactly how to handle the messages it receives, whether to push these messages to a specific queue or multiple queues, or discard the messages, which depends on the switch type
Queue: queue is a data structure used internally by RabbitMQ. Although messages flow through RabbitMQ and applications, they can only be stored in the queue. The queue is only constrained by the memory and disk limitations of the host. It is essentially a large message buffer.
consumer
Downloading and Installing RabbitMQ — RabbitMQ
install
Pull image:
docker pull rabbitmq:3.8.12-management-alpine
Start:
docker run -d --hostname rabbit_host1 --name xd_rabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq:3.8.12-management-alpine
Browser access: ip:15672
Basic concepts of rabbitMQ
1,TTL survival time
time to live message lifetime. If it is not consumed within the lifetime, it will be cleared
2. RabbitMQ supports two TTLS
ttl configuration with separate messages
Configure the whole queue ttl (mostly)
3. What is a dead letter queue
A queue in which messages that are not consumed in time are stored
4. Dead letter switch
When the message becomes a dead letter, it will be re sent to another switch, which is the dead letter switch
What kinds of situations can a message become a dead letter
1. The consumer rejects the message (basic.reject/basic.nack) and does not rejoin the queue. Request = false;
2. The message is not consumed in the queue and exceeds the expiration time TTL of the queue or the message itself
3. The message length of the queue has reached its limit
Note that after the message becomes a dead letter, if the queue is bound to the dead letter switch, the message will be rerouted to the dead letter queue by the dead letter switch.
Delay queue:
A message queue with delay function. After the producer sends the message to the server of the message queue, it does not want the message to be delivered immediately, but to be delivered to the consumer at a certain time after the current time point. The message is a timed message;
rocketMQ has the function of delay queue, but rabbitMQ does not. The delay function is realized through dead letter queue
As follows: consumers directly monitor the dead letter queue;
Using RabbitMQ
1. Import dependency
<!--Message queue--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
2. Add configuration to each project (configuration under spring)
# Message queue rabbitmq: host: 47.100.54.149 port: 5672 virtual-host: / username: admin password: password # Turn on manual confirmation message listener: simple: acknowledge-mode: manual
3. Create configuration files and configuration classes
mqconfig: # Delay queue, cannot be monitored coupon_release_delay_queue: coupon.release.delay.queue # A queue that forwards messages after they expire coupon_release_queue: coupon.release.queue # Switch coupon_event_exchange: coupon.event.exchange # Route key to delay queue coupon_release_delay_routing_key: coupon.release.delay.routing.key # When the message expires, enter the key to release the dead letter queue coupon_release_routing_key: coupon.release.routing.key # The time the message expires, in milliseconds ttl: 15000
@Configuration @Data public class RabbitMqconfig { /** * Switch */ @Value("${mqconfig.coupon_event_exchange}") private String eventExchange; /** * First queue delay queue */ @Value("${mqconfig.coupon_release_delay_queue}") private String couponReleaseDelayQueue; /** * Routing key of the first queue * Route key entering the queue */ @Value("${mqconfig.coupon_release_delay_routing_key}") private String couponReleaseDelayRoutingKey; /** * The second queue is the queue monitored to restore inventory */ @Value("${mqconfig.coupon_release_queue}") private String couponReleaseQueue; /** * Routing key of the second queue * That is, the routing key entering the dead letter queue */ @Value("${mqconfig.coupon_release_routing_key}") private String couponReleaseRoutingKey; /** * Expiration time */ @Value("${mqconfig.ttl}") private Integer ttl; /** * Message converter * @return */ @Bean public MessageConverter messageConverter(){ return new Jackson2JsonMessageConverter(); } /** * Define switch * Topic Type, or direct route * Generally, one microservice and one switch * @return */ @Bean public Exchange couponEventExchange(){ return new TopicExchange(eventExchange,true,false); } /** * Delay queue */ @Bean public Queue couponReleaseDelayQueue(){ Map<String,Object> args = new HashMap<>(); args.put("x-message-ttl",ttl); args.put("x-dead-letter-routing-key",couponReleaseRoutingKey); args.put("x-dead-letter-exchange",eventExchange); return new Queue(couponReleaseDelayQueue,true,false,false,args); } /** * Dead letter queue */ @Bean public Queue coupponReleaseQueue(){ return new Queue(couponReleaseQueue,true,false,false); } /** * Establishment of dead letter queue binding relationship * Establish the binding between the queue and the switch * @return */ @Bean public Binding couponReaseBinding(){ return new Binding(couponReleaseQueue,Binding.DestinationType.QUEUE,eventExchange,couponReleaseRoutingKey,null); } /** * The binding relationship of the first queue, the delay queue, is established * Establish the binding between the queue and the switch * @return */ @Bean public Binding couponReaseDelayBinding(){ return new Binding(couponReleaseDelayQueue,Binding.DestinationType.QUEUE,eventExchange,couponReleaseDelayRoutingKey,null); } }
@RunWith(SpringRunner.class) @SpringBootTest @Slf4j public class MQtest { @Autowired private RabbitTemplate rabbitTemplate; @Test public void sendDelayMsg(){ // When sending a message, there are three parameters: switch and routing key message body rabbitTemplate.convertAndSend("coupon.event.exchange","coupon.release.delay.routing.key","this is a coupon "); } }