Overview
RABBITMQ is an open-source message broker and queue Server used to share data between disparate applications through a common protocol, or simply to get the job queue to be processed by a distributed server.
It is realistic with the AMQP protocol and follows the Mozilla Public License Open source protocol, which supports multiple languages and can be easily integrated with spring.
Message Queuing uses messages to connect applications that are routed between applications through message proxies such as RABBITMQ.
Basic concepts
Broker
Message Queuing server entity used to process data
Vhost
The virtual message host created by the RABBITMQ server has its own permission mechanism, and a broker can open multiple vhost for different user's permission isolation, and Vhost is also completely isolated.
Productor
Generate data for message traffic
Channel
Message channel, multiple channels can be established in AMQP, and each channel represents a session task.
- Exchange
- Direct
Forwards the message to the queue specified by Routing-key
- Fanout
Forwards a message to all bound queues, similar to how a broadcast is sent.
- Topic
Forwarding messages according to the rules, which are more pattern-matching and more flexible
- Queue
- A queue is an internal object of RABBITMQ that stores messages
- In order to dynamically increase the number of consumers, the queue will receive messages in a poll (Round-robin) way evenly distributed to multiple consumers.
Binding
Represents the relationship between the switch and the queue, and when binding, with an additional parameter binding-key, to match the Routing-key.
Consumer
Listening for Message Queuing to read the message data
Springboot three types of Exchange Mode (FANOUT,DIRECT,TOPIC) implementation
Pom.xml references in SPRING-BOOT-STARTER-AMQP
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId></dependency>
Add RABBITMQ Configuration
spring: rabbitmq: host: localhost port: 5672 username: guest password: guest
Direct
Direct mode generally only needs to define queue using the self-bring switch (defaultexchange) without binding the switch
@Configurationpublicclass RabbitP2PConfigure { publicstaticfinal"p2p-queue"; @Bean publicqueue() { returnnewtrue); }}
@RunWith(Springrunner.class)@SpringBootTest(classes = bootcoretestapplication.)class)@Slf4j Public classrabbittest {@Autowired PrivateAmqptemplate amqptemplate;/*** Send */ @Test Public void Sendlazy()throwsinterruptedexception {City City =New City(234556666L,"Direct_name","Direct_code"); Amqptemplate.Convertandsend(Rabbitlazyconfigure.queue_name, city); }/*** Pick up */ @Test Public void Receive()throwsinterruptedexception {Object obj = amqptemplate.Receiveandconvert(Rabbitlazyconfigure.queue_name); Assert.Notnull(obj,""); Log.Debug(obj.toString()); }}
Applicable scenario: Point-to-point
Fanout
Fanout mode requires multiple queue bindings on the same switch
@Configuration Public classrabbitfanoutconfigure { Public Static FinalString Exchange_name ="Fanout-exchange"; Public Static FinalString fanout_a ="Fanout. A "; Public Static FinalString Fanout_b ="Fanout. B "; Public Static FinalString Fanout_c ="Fanout. C ";@Bean PublicQueueamessage() {return NewQueue (FANOUT_A); }@Bean PublicQueuebmessage() {return NewQueue (Fanout_b); }@Bean PublicQueueCmessage() {return NewQueue (Fanout_c); }@Bean PublicFanoutexchangeFanoutexchange() {return New Fanoutexchange(Exchange_name); }@Bean PublicBindingBindingexchangea(Queue amessage, Fanoutexchange fanoutexchange) {returnBindingbuilder.Bind(amessage). to(Fanoutexchange); }@Bean PublicBindingBindingexchangeb(Queue bmessage, Fanoutexchange fanoutexchange) {returnBindingbuilder.Bind(bmessage). to(Fanoutexchange); }@Bean PublicBindingBindingexchangec(Queue cmessage, Fanoutexchange fanoutexchange) {returnBindingbuilder.Bind(Cmessage). to(Fanoutexchange); }}
Sent by
@Slf4jpublicclass Sender { @Autowired private AmqpTemplate rabbitTemplate; publicvoidsendFanout(Object message) { log.debug("begin send fanout message<"">"); rabbitTemplate.convertAndSend(RabbitFanoutConfigure.EXCHANGE_NAME"", message); }}
We can use @rabbitlistener to monitor multiple queue for consumption
@Slf4j@RabbitListener(queues = { RabbitFanoutConfigure.FANOUT_A, RabbitFanoutConfigure.FANOUT_B, RabbitFanoutConfigure.FANOUT_C})publicclass Receiver { @RabbitHandler publicvoidreceiveMessage(String message) { log.debug("Received <"">"); }}
Applicable scenarios
- 大规模多用户在线(MMO)游戏可以使用它来处理排行榜更新等全局事件- 体育新闻网站可以用它来近乎实时地将比分更新分发给移动客户端- 分发系统使用它来广播各种状态和配置更新- 在群聊的时候,它被用来分发消息给参与群聊的用户
Topic
This pattern is more complex, in short, that each queue has its own topic of interest, all messages with a "caption", and Exchange forwards the message to a queue where all subjects of interest can match the routekey blur.
When binding, provide a topic that the queue cares about, such as "topic.# (" # "denotes 0 or several keywords," * "denotes a keyword.) )
@Configuration Public classrabbittopicconfigure { Public Static FinalString Exchange_name ="Topic-exchange"; Public Static FinalString TOPIC ="topic"; Public Static FinalString topic_a ="topic. A "; Public Static FinalString Topic_b ="topic. B ";@Bean PublicQueueQueuetopic() {return NewQueue (rabbittopicconfigure.TOPIC); }@Bean PublicQueueQueuetopica() {return NewQueue (rabbittopicconfigure.topic_a); }@Bean PublicQueueQUEUETOPICB() {return NewQueue (rabbittopicconfigure.Topic_b); }@Bean PublicTopicexchangeExchange() {Topicexchange Topicexchange =New Topicexchange(Exchange_name); Topicexchange.setdelayed(true);return New Topicexchange(Exchange_name); }@Bean PublicBindingBindingexchangetopic(Queue queuetopic, Topicexchange Exchange) {returnBindingbuilder.Bind(Queuetopic). to(Exchange). with(Rabbittopicconfigure.TOPIC); }@Bean PublicBindingBindingexchangetopics(Queue Queuetopica, Topicexchange Exchange) {returnBindingbuilder.Bind(Queuetopica). to(Exchange). with("topic.#"); }}
And listen to three queues at the same time.
@Slf4j@RabbitListener(queues = { RabbitTopicConfigure.TOPIC, RabbitTopicConfigure.TOPIC_A, RabbitTopicConfigure.TOPIC_B})publicclass Receiver { @RabbitHandler publicvoidreceiveMessage(String message) { log.debug("Received <"">"); }}
By testing we can find
@RunWith(Springrunner.class)@SpringBootTest(classes = bootcoretestapplication.)class) Public classrabbittest {@Autowired PrivateAmqptemplate rabbittemplate;@Test Public void Sendall() {rabbittemplate.Convertandsend(Rabbittopicconfigure.Exchange_name,"Topic.test","Send All"); }@Test Public void Sendtopic() {rabbittemplate.Convertandsend(Rabbittopicconfigure.Exchange_name, Rabbittopicconfigure.TOPIC,"Send Topic"); }@Test Public void Sendtopica() {rabbittemplate.Convertandsend(Rabbittopicconfigure.Exchange_name, Rabbittopicconfigure.topic_a,"Send Topica"); }}
Applicable scenarios
- 分发有关于特定地理位置的数据,例如销售点- 由多个工作者(workers)完成的后台任务,每个工作者负责处理某些特定的任务- 股票价格更新(以及其他类型的金融数据更新)- 涉及到分类或者标签的新闻更新(例如,针对特定的运动项目或者队伍)- 云端的不同种类服务的协调- 分布式架构/基于系统的软件封装,其中每个构建者仅能处理一个特定的架构或者系统。
Delay queue
- Deferred consumption:
If a user generates an order, it will take some time to check the payment status of the order, and if the order is still unpaid, the order will need to be closed in a timely manner.
After the user registration is successful, it takes a while to verify the user's usage after a week, and if the user is found to be less active, send an email or text message to remind the user to use it.
- Deferred retry:
If consumers fail to consume messages from the queue, they want to retry automatically after a period of delay.
If the delay queue is not used, then we can only do it through a polling scanner. This scheme is neither elegant nor convenient for a unified service to facilitate the use of developers. But with the delay queue, we can do it easily.
Set switch Delay property to True
@Configuration Public classrabbitlazyconfigure { Public Static FinalString queue_name ="Lazy-queue-t"; Public Static FinalString Exchange_name ="Lazy-exchange-t";@Bean PublicQueueQueue() {return NewQueue (Queue_name,true); }@Bean PublicDirectexchangeDefaultexchange() {Directexchange Directexchange =New Directexchange(Exchange_name,true,false); Directexchange.setdelayed(true);returnDirectexchange; }@Bean PublicBindingbinding() {returnBindingbuilder.Bind(Queue()). to(Defaultexchange()). with(queue_name); }}
Set delay time when sending
@Slf4j class Sender { @Autowired private amqptemplate rabbittemplate; public void sendlazy (Object msg) {log. debug ( "begin send Lazy message<" + msg + ); Rabbittemplate. convertandsend (Rabbitlazyconfigure. exchange_name , Rabbitlazyconfigure. queue_name , MSG, message, {message. (). setheader ( "X-delay" , 10000 ); return message; } ); }}
End
For various use cases, please view the official documents directly
Springboot Integrated RABBITMQ