RabbitMQ(笔记)
为什么使用RabbitMQ
- 流量削峰
- 应用解耦
- 异步处理
什么是AMQP?
- 应用间消息通信的一种协议,与语言和平台无关
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
-
application.yml
spring: rabbitmq: host: localhost port: 5672 username: guest #自己账号 password: guest #自己密码 virtual-host: / #虚拟主机
-
注解
-
@RabbitListener(queues = "zbl")
其中"zbl",为消息队列名称
-
@RabbitHandler
配合@RabbitListener(queues = "zbl")使用
-
1.Demo01
- 创建两个服务
- 开启RabbitMQ服务
- 引入依赖
- 配置文件
代码
登陆RabbitMq服务,创建队列“zbl”
http://ip地址:15672
-->登陆 -->选中导航栏的Queues -->找到下方按钮Add Queue
其中 Name:为队列名称
供应方
//注入RabbitTemplate
@Autowired
private RabbitTemplate rabbitTemplate;
public void test01() {
System.out.println("开始向队列中发送一条消息!");
// zbl:管理中的队列名 message:DragonDawson!:发送的消息
rabbitTemplate.convertAndSend("zbl", "message:DragonDawson!");
System.out.println("消息发送完毕!");
}
消费方
//@RabbitHandler
@RabbitListener(queues = "zbl")
public void test01(String message){
System.out.println("接收到的消息:"+message);
}
操作流程:
- 先启动供应方,将消息,加入队列
- 启动消费方,消息会从队列发送到消费方,并删除自身信息
2.消息发布与订阅
①Fanout(广播)
描述
-
与之前操作不同的是,将一个消息,同时放入多个队列中,从而分发给不同的消费方
-
在这里就按需引入“交换机”
-
那么这里也可以是多个交换机,每个交换机和队列都是相互绑定的
-
代码测试
配置类
import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MqOrderConfig { //交换机 @Bean public FanoutExchange fanoutExchange(){ return new FanoutExchange("dragon.fanout"); } //队列 @Bean public Queue fanOutQueue01(){ return new Queue("fanout.queue01"); } //队列和交换机绑定 @Bean public Binding bind01(Queue fanOutQueue01,FanoutExchange fanoutExchange){ return BindingBuilder.bind(fanOutQueue01).to(fanoutExchange); } //队列 @Bean public Queue fanOutQueue02(){ return new Queue("fanout.queue02"); } //队列和交换机绑定 @Bean public Binding bind02(Queue fanOutQueue02,FanoutExchange fanoutExchange){ return BindingBuilder.bind(fanOutQueue02).to(fanoutExchange); } }
消息发送
@Autowired private RabbitTemplate rabbitTemplate; public void testFanoutExchange() { // 交换机名称 String exchangeName = "dragon.fanout"; // 消息 String message = "hello, everyone!"; // 发送消息,参数分别是:交互机名称、RoutingKey(暂时为空)、消息 rabbitTemplate.convertAndSend(exchangeName, "", message); }
消息订阅
@RabbitListener(queues = "fanout.queue01") public void listenFanoutQueue1(String msg) { System.out.println("消费者1接收到Fanout消息:【" + msg + "】"); } @RabbitListener(queues = "fanout.queue02") public void listenFanoutQueue2(String msg) { System.out.println("消费者2接收到Fanout消息:【" + msg + "】"); }
②Direct(路由)
描述
和广播对比,多绑定了一个key,根据绑定对应的key去操作消息订阅预发布
代码测试
配置类
//direct交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("dragon.direct");
}
//队列
@Bean
public Queue dirOutQueue01(){
return new Queue("direct.queue01");
}
//绑定队列和交换机
@Bean
public Binding bind03(Queue dirOutQueue01,DirectExchange directExchange){
return BindingBuilder.bind(dirOutQueue01).to(directExchange).with("red");
}
//队列
@Bean
public Queue dirOutQueue02(){
return new Queue("direct.queue02");
}
//绑定队列和交换机
@Bean
public Binding bind02(Queue dirOutQueue04,DirectExchange directExchange){
return BindingBuilder.bind(dirOutQueue04).to(directExchange).with("blue");
}
消息发送
@Test
public void testDirectExchange() {
// 队列名称
String exchangeName = "dragon.direct";
// 消息
String message = "hello, everyone!";
// 发送消息,参数分别是:交互机名称、RoutingKey(red)、消息
rabbitTemplate.convertAndSend(exchangeName, "red", message);
}
消息订阅
@RabbitListener( bindings = @QueueBinding(
value = @Queue("direct.queue01"),
exchange = @Exchange(value = "dragon.direct",type = ExchangeTypes.DIRECT),
key = {"red","blue"}
))
public void listenDirectQueue1(String msg) {
System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}
@RabbitListener( bindings = @QueueBinding(
value = @Queue("direct.queue02"),
exchange = @Exchange(value = "dragon.direct",type = ExchangeTypes.DIRECT),
key = {"yellow","blue"}
))
public void listenDirectQueue2(String msg) {
System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
在这个过程中,交换机只会绑定red的队列
消息也只会发送到red的服务端
③Topic(话题)
描述
配置类
//topic交换机
@Bean
public TopicExchange topicExchange(){
return new TopicExchange("dragon.topic");
}
//队列
@Bean
public Queue topicQueue04(){
return new Queue("topic.queue02");
}
@Bean
public Binding bind05(Queue topicQueue04,TopicExchange topicExchange){
return BindingBuilder.bind(topicQueue04).to(topicExchange).with("dragon.topic");
}
//队列
@Bean
public Queue topicQueue05(){
return new Queue("topic.queue03");
}
@Bean
public Binding bind06(Queue topicQueue05,TopicExchange topicExchange){
return BindingBuilder.bind(topicQueue05).to(topicExchange).with("dawson.#");
}
消息发送
@Test
public void testFanoutExchange() {
// 队列名称
String exchangeName = "dragon.topic";
// 消息
String message = "hello, everyone!";
// 发送消息,参数分别是:交互机名称、RoutingKey(暂时为空)、消息
rabbitTemplate.convertAndSend(exchangeName, "dragon.#", message);
}
消息订阅
@RabbitListener( bindings = @QueueBinding(
value = @Queue("topic.queue02"),
exchange = @Exchange(value = "dragon.topic",type = ExchangeTypes.TOPIC),
key = {"dragon.first"}
))
public void listenFanoutQueue1(String msg) {
System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}
@RabbitListener( bindings = @QueueBinding(
value = @Queue("topic.queue03"),
exchange = @Exchange(value = "dragon.topic",type = ExchangeTypes.TOPIC),
key = {"dawson.FFF"}
))
public void listenFanoutQueue2(String msg) {
System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}