文章學習Demo為springboot(八):RabbitMQ詳解
1.Windows安裝RabbitMQ
????首先需要安裝ErLang語言支持腺怯,再安裝RabbitMQ(因為RabbitMQ是使用ErLang語言編寫的)皮获。啟動RabbitMQ服務直接去D:\軟件安裝包\RabbitMQ\rabbitmq_server-3.7.4\sbin文件下,雙擊rabbitmq-server.bat即可掐松。
????運行成功如下所示:
RabbitMQ核心知識:交換機,路由鍵
exchange交換機機制
什么是交換機
rabbitmq的message model實際上消息不直接發(fā)送到queue中,中間有一個exchange是做消息分發(fā),producer甚至不知道消息發(fā)送到那個隊列中去看峻。因此,當exchange收到message時衙吩,必須準確知道該如何分發(fā)互妓。是append到一定規(guī)則的queue,還是append到多個queue中,還是被丟棄冯勉?這些規(guī)則都是通過exchagne的4種type去定義的澈蚌。
The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.
Instead, the producer can only send messages to an exchange. An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.
exchange是一個消息的agent章姓,每一個虛擬的host中都有定義仇冯。它的職責是把message路由到不同的queue中。
binding爱咬?
exchange和queue通過routing-key關聯(lián)交胚,這兩者之間的關系是就是binding份汗。如下圖所示,X表示交換機,紅色表示隊列承绸,交換機通過一個routing-key去binding一個queue裸影,routing-key有什么作用呢?看Direct exchange類型交換機军熏。
Directed Exchange
路由鍵exchange轩猩,該交換機收到消息后會把消息發(fā)送到指定routing-key的queue中。那消息交換機是怎么知道的呢荡澎?其實均践,producer deliver消息的時候會把routing-key add到 message header中。routing-key只是一個messgae的attribute摩幔。
A direct exchange delivers messages to queues based on a message routing key. The routing key is a message attribute added into the message header by the producer. The routing key can be seen as an "address" that the exchange use to decide how to route the message. A message goes to the queue(s) whose binding key exactly matches the routing key of the message.
Default Exchange
這種是特殊的Direct Exchange彤委,是rabbitmq內(nèi)部默認的一個交換機。該交換機的name是空字符串或衡,所有queue都默認binding 到該交換機上焦影。所有binding到該交換機上的queue,routing-key都和queue的name一樣封断。
Topic Exchange
通配符交換機斯辰,exchange會把消息發(fā)送到一個或者多個滿足通配符規(guī)則的routing-key
的queue。其中表號匹配一個word坡疼,#匹配多個word和路徑彬呻,路徑之間通過.隔開。如滿足a..c的routing-key有a.hello.c柄瑰;滿足#.hello的routing-key有a.b.c.helo闸氮。
Fanout Exchange
扇形交換機,該交換機會把消息發(fā)送到所有binding到該交換機上的queue教沾。這種是publisher/subcribe模式蒲跨。用來做廣播最好。
所有該exchagne上指定的routing-key都會被ignore掉授翻。
The fanout copies and routes a received message to all queues that are bound to it regardless of routing keys or pattern matching as with direct and topic exchanges. Keys provided will simply be ignored.
Header Exchange
設置header attribute參數(shù)類型的交換機财骨。
2.Demo核心知識
2.1 RabbitMQ默認連接信息為:
spring-boot下的application.properties文件
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
2.2 最簡單的HelloTest:
發(fā)送者:
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class HelloSender {
@Autowired
private AmqpTemplate rabbitTemplate;
public void send() {
String context = "hello " + "JadenOliver";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("hello", context);
}
}
接收者:
@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {
@RabbitHandler
public void process(String hello) {
System.out.println("Receiver : " + hello);
}
}
注意點:
1>發(fā)送者和接收者的queue name必須一致镐作,不然不能接收;(本例中為"hello")
2>接收者接收信息的隊列名稱為:"hello":如果這個"hello"隊列沒有自定義生成隆箩,RabbitMQ會默認去生成该贾,親測。
2.3 一對多發(fā)送和多對多發(fā)送:
一對多發(fā)送:一個發(fā)送者捌臊,多個接收者杨蛋。結果:多個接收者均勻接收
Receiver 1: spirng boot neo queue ****** 84
Receiver 1: spirng boot neo queue ****** 86
Receiver 2: spirng boot neo queue ****** 85
Receiver 2: spirng boot neo queue ****** 88
Receiver 1: spirng boot neo queue ****** 87
Receiver 2: spirng boot neo queue ****** 89
Receiver 1: spirng boot neo queue ****** 90
Receiver 2: spirng boot neo queue ****** 91
Receiver 1: spirng boot neo queue ****** 92
Receiver 2: spirng boot neo queue ****** 93
Receiver 1: spirng boot neo queue ****** 94
Receiver 2: spirng boot neo queue ****** 95
Receiver 1: spirng boot neo queue ****** 96
Receiver 2: spirng boot neo queue ****** 97
Receiver 1: spirng boot neo queue ****** 98
Receiver 2: spirng boot neo queue ****** 99
多對多發(fā)送:多個發(fā)送者,多個接收者理澎。結果:多個接收者均勻接收
Receiver 1: spirng boot neo queue ****** 93
Receiver 2: spirng boot neo queue ****** 93
Receiver 1: spirng boot neo queue ****** 94
Receiver 2: spirng boot neo queue ****** 94
Receiver 1: spirng boot neo queue ****** 95
Receiver 2: spirng boot neo queue ****** 95
Receiver 1: spirng boot neo queue ****** 96
Receiver 2: spirng boot neo queue ****** 96
Receiver 1: spirng boot neo queue ****** 97
Receiver 2: spirng boot neo queue ****** 97
Receiver 1: spirng boot neo queue ****** 98
Receiver 2: spirng boot neo queue ****** 98
Receiver 1: spirng boot neo queue ****** 99
Receiver 2: spirng boot neo queue ****** 99
2.4 消息隊列高級使用:發(fā)送對象類型
發(fā)送對象不需要額外配置逞力,和發(fā)送普通數(shù)據(jù)類型類似
//發(fā)送者
public void send(User user) {
System.out.println("Sender object: " + user.toString());
this.rabbitTemplate.convertAndSend("object", user);
}
...
//接收者
@RabbitHandler
public void process(User user) {
System.out.println("Receiver object : " + user);
}
結果:
Sender object: User{name='neo', pass='123456'}
Receiver object : User{name='neo', pass='123456'}
Topic交換機使用
topic 是RabbitMQ中最靈活的一種方式,可以根據(jù)routing_key自由的綁定不同的隊列
首先對topic規(guī)則配置糠爬,這里使用兩個隊列來測試
@Configuration
public class TopicRabbitConfig {
final static String message = "topic.message";
final static String messages = "topic.messages";
@Bean
public Queue queueMessage() {
return new Queue(TopicRabbitConfig.message);
}
@Bean
public Queue queueMessages() {
return new Queue(TopicRabbitConfig.messages);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}
@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}
說明:
1> queueMessage和queueMessages兩個隊列寇荧,都和exchange交換機關聯(lián)起來;
2> 路由鍵對應分發(fā):如果路由鍵滿足"topic.message"执隧,exchange交換機把消息發(fā)送到queueMessage隊列揩抡;
如果路由鍵匹配"topic.#"模式,exchange交換機把消息發(fā)送到queueMessages隊列镀琉。
???這個交換機和路由鍵的配置極大的提高了RabbitMQ的靈活性峦嗤。
public void send1() {
String context = "hi, i am message 1";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
}
public void send2() {
String context = "hi, i am messages 2";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);
}
發(fā)送send1會匹配到topic.#和topic.message 兩個Receiver都可以收到消息,發(fā)送send2只有topic.#可以匹配所有只有Receiver2監(jiān)聽到消息