RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用。
队列服务, 通常存在三个概念: 发消息者、队列、收消息者,RabbitMQ 在此基础之上, 多做了一层抽象, 在发消息者和 队列之间, 加入了交换器 (Exchange). 这样发消息者和队列就没有直接联系, 转而变成发消息者把消息给交换器, 交换器根据调度策略再把消息再给队列。
生产者们就是负责推送消息服务,把消息推送到中间RabbitMQ Server中,在经过服务器中的交换机和队列等将数据进行处理后,发送到消费者方
常用交换机有三种: Direct Exchange (直连交换机) Topic Exchange (主题交换机) Fanout Exchange (扇形交换机)
Direct Exchange (直连交换机)
Direct Exchange是RabbitMQ默认的交换机模式,也是最简单的模式,根据key全文匹配去寻找队列。
Topic Exchange (主题交换机)
Topic Exchange 转发消息主要是根据通配符。 在这种交换机下,队列和交换机的绑定会定义一种路由模式,那么,通配符就要在这种路由模式和路由键之间匹配后交换机才能转发消息。
在这种交换机模式下:
路由键必须是一串字符,用句号(.
) 隔开,比如说 hello.rabbit,或者 hello.rabbit.mq等。
路由模式必须包含一个 星号(*
),主要用于匹配路由键指定位置的一个单词。 井号(#)就表示相当于一个或者多个单词。
Fanout Exchange
Fanout Exchange 消息广播的模式,不管路由键或者是路由模式,会把消息发给绑定给它的全部队列,如果配置了routing_key会被忽略。
创建一个Direct Exchange (直连交换机)的项目
创建完项目之后配置application.properties
server.port=8888
spring.application.name=spring-boot-rabbitmq-provider
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=root
spring.rabbitmq.password=root
spring.rabbitmq.virtual-host=my_vhost
ps:虚拟host配置项,我自己在rabbitmq服务上创建了自己的虚拟host,所以我配置了my_vhost,也可以选择不创建。自行下载安装rabbitmq。
创建 Direct Exchange (直连交换机)的配置文件config
@Configuration
public class RabbitConfig {
@Bean
public Queue DirectQueue() {
return new Queue("DirectQueue",true);
}
@Bean
DirectExchange DirectExchange() {
return new DirectExchange("DirectExchange",true,false);
}
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(DirectQueue()).to(DirectExchange()).with("DirectRouting");
}
}
在config中创建了一个消息队列取名为 DirectQueue, 创建了一个 Exchange 交换机名为 DirectExchange,可以不写。还有绑定交换机和队列的方法,利用这个key去寻找队列
发送者controller
@RestController
public class SendMessageController {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* Direct Exchange是RabbitMQ默认的交换机模式,也是最简单的模式,根据key全文匹配去寻找队列。
* @return
*/
@GetMapping("/sendMessage")
public String sendMessage() {
String msgId = String.valueOf(UUID.randomUUID());
String msgData = "测试直连交换机MQ";
String sendTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Map<String, Object> map = new HashMap<>();
map.put("msgId", msgId);
map.put("msgData", msgData);
map.put("sendTime", sendTime);
rabbitTemplate.convertAndSend("DirectExchange", "DirectRouting", map);
return "msg send success";
}
}
接收者
@Component
@RabbitListener(queues = "DirectQueue")
public class DirectReceiver {
@RabbitHandler
public void process(Map testMessage) {
System.out.println("第一个消费者收到信息:" + testMessage.toString());
}
}
注意,发送者和接收者的队列名queue name必须一致,不然不能接收
然后运行请求发送者路由http://localhost:8888/sendMessage 在rabbitMq服务器中就能看见用户推送的请求
创建多个接收者进行测试
所有消费者都会均匀的接收到信息。