SpringBoot教程(一) | SpringBoot集成RabbitMq(基础版)
(一)rabbitMq是什么
介绍
RabbitMq是我们在开发过程中经常会使用的一种消息队列。
RabbitMQ是一个开源的消息代理和队列服务器,用来实现各个应用服务间的数据共享(跨平台 ,跨语言)。
RabbitMQ是使用erlang语言编写的,并且基于AMQP协议实现。
所有的消息队列产品模型抽象上来说,都是类似的过程。
生产者创建消息,然后发布到消息队列中,由消费者进行消费。
适合场景
RabbitMQ是一个传统的消息队列系统,它采用了基于消息队列的发布-订阅模型。
消息被发布到队列中,然后由消费者按顺序处理。
RabbitMQ适用于需要低延迟
、高吞吐量
的消息传递场景,如金融交易、事件驱动架构等。
(二)rabbitMq的后台管理界面
安装完rabbitMq后,输入http://ip:15672/ ,是可以看到一个简单后台管理界面的。
在这个界面里面我们可以做些什么?
可以手动创建虚拟host,创建用户,分配权限,创建交换机,创建队列等等,还有查看队列消息,消费效率,推送效率等等。
以上这些管理界面的操作在这篇暂时不做扩展描述,我想着重介绍后面实例里会使用到的。
(三)消息推送的简述
首先先介绍一个简单的一个消息推送到接收的流程,提供一个简单的图:
黄色的圈圈就是我们的消息推送服务,将消息推送到 中间方框里面也就是 rabbitMq的服务器,
然后经过服务器里面的交换机、队列等各种关系(后面会详细讲)将数据处理入列后,
最终右边的蓝色圈圈消费者获取对应监听的消息。
(四)必须要明白的概念
1.我们发送消息需要指定交换机
2.队列(Queue )、交换机(…Exchange )、绑定(Binding )这个3个参数是必须设置的
3.路由键(Routing Key)这个参数是 在使用 直连型交换机、主题交换机 必须设置的
4.标头交换机匹配AMQP消息的使用的是 header,该交换机性能比较差,可被直连型交换机替代
交换机(Exchange )目前常见的有四种类型:
direct(直连型交换机)、fanout(扇型交换机)、
topic(主题交换机)、headers(标头交换机)。
(五)交换机介绍
1. direct 直连型交换机(RabbitMq默认的交换机类型,也是最常用的)
Binding 的含义:
绑定, 用于交换机和消息列队之间的关联。
一个绑定就是基于路由键(routing-key)将交换机和消息队列连接起来的路由规则。
所以可以将交换机理解成一个由绑定构成的路由表。
BindingBuilder的构成
Binding的由 队列(Queue)、交换机(Exchange)和路由键(Routing Key)相关联构成
消息中的路由键(routing key)如果和Binding中的bing key一致,交换机就将消息发送到队列的队列中。路由键要完全匹配,单个传播
。
简述: 通过指定直连型交换机发送消息 根据 传入的路由键 找到Binding 再获取Binding里面的队列,然后再存到这个队列中去。
2. fanout 扇型交换机
每个发到fanout扇型交换机的消息都会分到所有绑定的队列上去。
fanout交换器扇型交换机不处理路由键,只是简单的将队列绑定到交换机上,每个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。
很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout类型转发消息是最快的
。
3. topic 主题交换机
topic主题交换机通过模式匹配分配路由的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。
它将路由键和绑定键的字符串切分成单词,这些单词之间用.隔开。它同样会识别两个通配符: # 和* 。 #匹配0个或多个单词, * 匹配一个单词
(六)springBoot集成RabbitMQ( 实测)
SpringBoot集成rabbitMQ还是比较简单的,因为springBoot使用RabbitTemplate对常用操作进行了封装。
引入maven依赖
接下来我们来看一下集成过程。首先导入依赖。
<!-- AMQP客户端 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
添加MQ的配置
然后在springBoot的配置文件 application.yml中配置rabbitMQ连接信息
server:
port: 7890
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
扩展:
RabbitMQ的主要端口包括 4369(epmd)、5672(AMQP)、15672(管理界面)和 25672(节点间通信)
我们java程序连接使用的端口是 5672,管理端界面用的端口是 15672 访问
接下来我们我们分三种交换机进行演示。
1. direct 直连型交换机
(一) 创建配置类
首先是配置类,在配置类中我们需要声明交换机,队列和绑定关系。
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DirectExchangeConfig {
//定义队列的名称常量
public static final String DIRECT_QUEUE = "directQueue";
public static final String DIRECT_QUEUE2 = "directQueue2";
//定义直接交换机的名称常量
public static final String DIRECT_EXCHANGE = "directExchange";
//定义路由键常量,用于交换机和队列之间的绑定
public static final String DIRECT_ROUTING_KEY = "direct";
//定义队列,名称为DIRECT_QUEUE
@Bean
public Queue directQueue() {
//第二个参数表示持久化队列,不排他,不自动删除
return new Queue(DIRECT_QUEUE, true);
}
//定义队列,名称为DIRECT_QUEUE2
@Bean
public Queue directQueue2() {
//第二个参数表示持久化队列,不排他,不自动删除
return new Queue(DIRECT_QUEUE2, true);
}
//定义直接交换机
@Bean
public DirectExchange directExchange() {
//第二个参数表示持久化,第三个参数表示不自动删除
return new DirectExchange(DIRECT_EXCHANGE, true, false);
}
//定义一个绑定,将directQueue队列绑定到directExchange交换机上,
//使用direct作为路由键
@Bean
public Binding bindingDirectExchange(Queue directQueue, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue).to(directExchange).with(DIRECT_ROUTING_KEY);
}
// 定义一个绑定Bean,将directQueue2队列也绑定到directExchange交换机上,
// 同样使用direct作为路由键
@Bean
public Binding bindingDirectExchange2(Queue directQueue2, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue2).to(directExchange).with(DIRECT_ROUTING_KEY);
}
}
这里我们创建了一个叫directExchange的交换机,绑定了directQueue和directQueue2两个队列,路由键都为是direct.
这意味着发送到directExchange交换机且路由键为direct的消息将同时被directQueue和directQueue2接收
(二)消息生产者
消息的生产者,我们通过一个Controller来进行模拟,直接引用rabbitTemplate
@RestController
@Slf4j
@RequestMapping("/direct")
public class DirectController {
private final RabbitTemplate rabbitTemplate;
public DirectController(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
/**
* direct交换机为直连模式交换机
* 根据消息携带的路由键将消息投递给对应队列
*
*
* @return
*/
@GetMapping("send")
public Object sendMsg() {
rabbitTemplate.convertAndSend(DirectExchangeConfig.DIRECT_EXCHANGE, DirectExchangeConfig.DIRECT_ROUTING_KEY, "发送一条测试消息:direct");
return "direct消息发送成功!!";
}
}
当我在浏览器访问对应连接的时候,就会生产一条消息发送到directExchange交换机,路由key为:direct, 消息内容为:发送一条测试消息:direct
(三)消息消费者
接下来我们来看消息的消费者。
package com.lsqingfeng.action.rabbitmq.direct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @className: DirectQueueListener
* @description: 直连交换机的监听器
* @author: sh.Liu
* @date: 2021-08-23 16:03
*/
@Slf4j
@Component
public class DirectQueueListener {
/**
* 尽管设置了两个消费者,但是只有一个能够消费成功
* 多次发送则轮训消费:
* DirectReceiver消费者收到消息1 : 发送一条测试消息:direct
* DirectReceiver消费者收到消息2 : 发送一条测试消息:direct
* DirectReceiver消费者收到消息1 : 发送一条测试消息:direct
* DirectReceiver消费者收到消息2 : 发送一条测试消息:direct
*
* 一个交换机可以绑定多个队列。如果通过路由key可以匹配到多个队列,消费的时候也只能有一个进行消费
* @param testMessage
*/
@RabbitHandler
@RabbitListener(queues = DirectExchangeConfig.DIRECT_QUEUE)
public void process(String testMessage) {
System.out.println("DirectReceiver消费者收到消息1 : " + testMessage + "\n");
}
@RabbitHandler
@RabbitListener(queues = DirectExchangeConfig.DIRECT_QUEUE)
public void process2(String testMessage) {
System.out.println("DirectReceiver消费者收到消息2 : " + testMessage + "\n")