**MQ, also known as Message Queue, is a middleware for asynchronous communication** It can be understood as the post office. The sender delivers the message to the post office, and then the post office helps us send it to the specific message receiver (consumer). We don't need to care about the specific sending process and time, and it won't interfere with other things. Common MQS include kafka, activemq, zeromq, rabbitmq, etc. the comparison, advantages and disadvantages of each MQ can be determined by themselves
rabbitmq
RabbitMQ follows AMQP protocol and is developed by Erlang language for high concurrency. It is used for real-time message transmission with high reliability requirements and supports multi language clients. Support delay queue (this is a very useful function)
Basic concepts
**Broker: * * is simply a message queuing server entity
**Exchange: * * message switch, which specifies the rules by which messages are routed to which queue
**Queue: * * message queue carrier. Each message will be put into one or more queues
**Binding: * * binding, which is used to bind exchange and queue according to routing rules
**Routing Key: * * routing keyword. exchange delivers messages based on this keyword
**vhost: * * virtual host. Multiple vhosts can be set up in a broker to separate the permissions of different users
**Producer: * * message producer is the program that delivers messages
**Consumer: * * message consumer is the program that receives messages
**Channel: * * message channel. Multiple channels can be established in each connection of the client, and each channel represents a session task
Based on centos7 X for installation, refer to: http://blog.battcn.com/2017/08/20/linux/linux-centos7-ribbitmq/
Common application scenarios
- Email sending: after the user registers, the message is delivered to rabbitmq, and the message consumer sends the message asynchronously to improve the system response speed
- Traffic peak clipping: it is generally widely used in seckill activities. Seckill will cause the application to hang up due to excessive traffic. In order to solve this problem, the message queue is generally added to the front end of the application. It is used to control the number of active people and directly discard orders exceeding this certain threshold. Ease short-term high flow crushing applications.
- Order timeout: using rabbitmq's delay queue, you can easily realize the function of order timeout. For example, the user cancels the order 30 minutes after placing the order without paying
- There are more application scenarios not listed one by one
Import dependency
In POM Add the dependency of spring boot starter AMQP in XML
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Property configuration
Application rabbitmq is configured in the properties file. It is worth noting that the switch of manual ACK is configured here
spring.rabbitmq.username=battcn spring.rabbitmq.password=battcn spring.rabbitmq.host=192.168.0.133 spring.rabbitmq.port=5672 spring.rabbitmq.virtual-host=/ # Manual ACK does not enable the automatic ACK mode. The purpose is to prevent the loss of incorrectly processed messages after an error is reported. The default is none spring.rabbitmq.listener.simple.acknowledge-mode=manual
Specific coding
Define queue
If the queue has been created manually or already exists in RabbitMQ, you can also omit the following code
package com.battcn.config; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * RabbitMQ to configure * * @author Levin * @since 2018/4/11 0011 */ @Configuration public class RabbitConfig { public static final String DEFAULT_BOOK_QUEUE = "dev.book.register.default.queue"; public static final String MANUAL_BOOK_QUEUE = "dev.book.register.manual.queue"; @Bean public Queue defaultBookQueue() { // The first is the name of QUEUE, and the second is whether the message needs persistence return new Queue(DEFAULT_BOOK_QUEUE, true); } @Bean public Queue manualBookQueue() { // The first is the name of QUEUE, and the second is whether the message needs persistence return new Queue(MANUAL_BOOK_QUEUE, true); } }
Entity class
Create a Book class
public class Book implements java.io.Serializable { private static final long serialVersionUID = -2164058270260403154L; private String id; private String name; // Omit get set }
controller
Write a Controller class for message sending
package com.battcn.controller; import com.battcn.config.RabbitConfig; import com.battcn.entity.Book; import com.battcn.handler.BookHandler; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Levin * @since 2018/4/2 0002 */ @RestController @RequestMapping(value = "/books") public class BookController { private final RabbitTemplate rabbitTemplate; @Autowired public BookController(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } /** * this.rabbitTemplate.convertAndSend(RabbitConfig.DEFAULT_BOOK_QUEUE, book); Corresponding to {@ link BookHandler#listenerAutoAck} * this.rabbitTemplate.convertAndSend(RabbitConfig.MANUAL_BOOK_QUEUE, book); Corresponding to {@ link bookhandler #listener manualack} */ @GetMapping public void defaultMessage() { Book book = new Book(); book.setId("1"); book.setName("Let's learn together Spring Boot"); this.rabbitTemplate.convertAndSend(RabbitConfig.DEFAULT_BOOK_QUEUE, book); this.rabbitTemplate.convertAndSend(RabbitConfig.MANUAL_BOOK_QUEUE, book); } }
Message consumer
By default, {spring boot data AMQP} is an automatic ack mechanism, which means that MQ will automatically help us to ack after message consumption. In this way, there is a problem with dependency: if an error is reported, the message will not be lost and will be consumed in an infinite cycle. It is easy to run out of disk space. Although the number of consumption can be configured, this approach is also elegant. At present, it is recommended that we manually ACK and then transfer the consumption error message to other message queues for compensation
package com.battcn.handler; import com.battcn.config.RabbitConfig; import com.battcn.entity.Book; 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; /** * BOOK_QUEUE consumer * * @author Levin * @since 2018/4/11 0011 */ @Component public class BookHandler { private static final Logger log = LoggerFactory.getLogger(BookHandler.class); /** * <p>TODO This scheme is the default method of spring boot data AMQP and is not recommended. For details, it is recommended to use listener manual ack ()</p> * By default, if manual ACK is not configured, Spring Data AMQP will automatically help us to ACK after message consumption * Existing problems: if an error is reported, the message will not be lost, but it will be consumed in an infinite cycle. If the error log is enabled, it is easy to run out of disk space * Solution: manually ACK or try catch, and then transfer the error message in the catch to other series * spring.rabbitmq.listener.simple.acknowledge-mode=manual * <p> * * @param book Listening content */ @RabbitListener(queues = {RabbitConfig.DEFAULT_BOOK_QUEUE}) public void listenerAutoAck(Book book, Message message, Channel channel) { // If you manually ACK TODO, the message will be monitored and consumed, but the message still exists in the queue. If acknowledge mode is not configured, it will automatically ACK after consumption final long deliveryTag = message.getMessageProperties().getDeliveryTag(); try { log.info("[listenerAutoAck Monitored messages] - [{}]", book.toString()); // TODO notifies MQ that the message has been successfully consumed and can be ACK channel.basicAck(deliveryTag, false); } catch (IOException e) { try { // TODO processing failed, press MQ again channel.basicRecover(); } catch (IOException e1) { e1.printStackTrace(); } } } @RabbitListener(queues = {RabbitConfig.MANUAL_BOOK_QUEUE}) public void listenerManualAck(Book book, Message message, Channel channel) { log.info("[listenerManualAck Monitored messages] - [{}]", book.toString()); try { // TODO notifies MQ that the message has been successfully consumed and can be ACK channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (IOException e) { // If TODO reports an error, we can carry out fault-tolerant processing, such as transferring the current message to other queues } } }
Main function
package com.battcn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author Levin */ @SpringBootApplication public class Chapter11Application { public static void main(String[] args) { SpringApplication.run(Chapter11Application.class, args); } }
test
After completing the preparations, start Chapter11Application} access http://localhost:8080/books You will see the following, which means that everything is normal
2018-05-22 19:04:26.708 INFO 23752 --- [cTaskExecutor-1] com.battcn.handler.BookHandler : [listenerAutoAck Monitored messages] - [com.battcn.entity.Book@77d8be18] 2018-05-22 19:04:26.709 INFO 23752 --- [cTaskExecutor-1] com.battcn.handler.BookHandler : [listenerManualAck Monitored messages] - [com.battcn.entity.Book@8bb452]
summary
At present, many leaders have written tutorials on SpringBoot. If there are similarities, please forgive me. This tutorial is based on the latest spring boot starter parent: 2.0.2 Release, including the features of the new version, will be introduced together
4. Perception
In the recent interview, I have the following insights:
-
Telephone interview is more reliable than video interview
Video interviews are a bit awkward and sometimes get stuck. In contrast, telephone interviews don't have these problems
I prefer the form of telephone interview
-
Make more preparations before the interview
On the second day after returning to work, I met the first company and was completely in no state. The answer was a mess
It is suggested that you should adjust your state before the interview, especially if the Spring Festival is a little long in your house
-
It must be targeted
Be sure to have a certain understanding of the company you post, so as to avoid wasting the time of both parties if you pass the interview and don't want to go
It is recommended that you spend more time to understand your post and company