好久没用过rabbitmq了,方便记忆,想着整理整理.
1.安装rabbitmq
我选择的环境为docker,还不了解docker的小伙伴建议去看看,非常赞哦.
1.安装,我这里选择安装management版的,management自带web操作页面的版本.
docker pull rabbitmq:3.7.15-management
2.启动:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672
-v `$pwd`/data:/var/lib/rabbitmq --hostname myrabbit
-e RABBITMQ_DEFAULT_USER=guest
-e RABBITMQ_DEFAULT_PASS=guest
rabbitmq:3.7.14-management
3 .测试是否启动成功.
docker ps //看到服务说明启动成功
localhost:15672 //浏览器访问
至此,rabbitmq安装成功.
2.消息服务基本介绍
简单介绍一下消息服务,加深印象.
为什么要使用消息服务呢?
大多应用中,可以通过消息中间件来提高系统的异步通信能力,解耦能力.
应用场景:
异步处理 , 解耦 , 流量削峰
消息服务中两个重要的概念.
1.消息代理(message broker)
2.目的地(destination)
当消息发送者发送消息后,将由消息代理接管.消息代理就保证我们的消息到达指定的目的地.
消息队列主要有两种形式的目的地:
1.队列(queue):点对点式的消息通信
2.主题(topic): 发布/订阅 式的消息通信
点对点:
一对一,消息发布者发布消息后,消息代理将其放到指定队列中,消息接收者
从队列中获取消息内容,消息被消息接收者读取之后将会被移除队列.
消息发布者和接受者都是唯一的(指同一条消息只会被一个消息接收者接收)
发布订阅式:
消息发布者 发送消息到主题,多个消息接收者监听这个主题,同时接收到达主题的消息.
消息服务分为JMS和AMQP两种:
JMS(Java Message Service):
基于JVM消息代理的规范.如ActiveMQ是JMS的实现.
受java语言的限制,只允许在java语言中使用.
AMQP(Advanced Message Queuing Protocol)
高级消息队列协议,也是消息代理的一个规范,兼容JMS
我们本文所要描述的rabbitmq是AMQP的实现.
3.Rabbitmq基本介绍
RabbitMQ简介:
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现
核心概念:
Message:
消息,由消息头和消息体组成. 消息体是不透明的,而消息头则是由一系列的可选属性组成的,这些属性包括 routing-key (路由键) , priority (相对于其他消息的优先权) ,delivery-mode(指出该消息是否需要持久存储)等.
Publisher:
消息生产者,也是向交换器发布消息的客户端应用程序.
Exchange:
交换器,用来接收消息生产者发送的消息,并将这些消息路由给服务器中的队列.
Exchange有4中类型 : direct(默认) , fanout , topic , headers , 不同类型的交换器转发消息具有不同的策略.
Queue:
消息队列,用来保存消息知道发送给消费者 , 是消息的容器 , 也是消息的坟墓 ,
消息会一直存放在消息队列中,知道消费者连接到这个队列将其取走.
Binding:
绑定,用于消息队列和交换器之间的关联, 一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解为一个由绑定构成的路由表.Exchange和Queue的绑定是可以多对多的关系.
Connection:
网络连接.如tcp连接
Channel:
信道 , 多路复用连接中的一条独立的双向数据通道.信道是建立在真实的TCP连接内的虚拟连接,AMQP命令都是通过信道发出去的, 不管是发布消息 ,订阅队列还是接收消息 , 这些动作都是通过信道完成的. 因为对操作系统来说,建立和销毁tcp都是非常昂贵的开销,所以引入了信道的概念 , 以复用一条TCP连接.
Consumer:
消息消费者, 表示一个从消息队列中获得消息的客户端应用程序.
Virtual Host:
虚拟主机, 表示一批交换器 , 消息队列 和相关对象. 虚拟主机是共享相同的身份认证和加密环境的独立服务器域. 每个 虚拟主机本质上就是一个mini版的Rabbitmq服务器, 拥有自己的队列,交换器 , 绑定 和 权限机制 . 虚拟主机 是AMQP概念的基础 , 必须在连接时指定 , RabbitMq默认的vhost 是 /
Broker:
表示消息队列服务器的实体
4.rabbitmq中Exchange类型
Exchange分发消息时根据类型的不同分发策略有所区别,目前共四种类型:
1.direct
2.fanout
3.topic
4.headers(headers匹配AMQP消息的header而不是路由键,与direct完全一致,且性能较差,基本使用不到)
Direct Exchange:
消息中的路由键(routing key)如果和Binding中的binding key 完全一致,交换器就将消息发送到对应的消息队列中.它是完全匹配,单播的模式.
Fanout Exchange:
每个发到fanoutExchange 类型交换器的消息都会分到交换器所绑定的所有消息队列上.fanout交换器不会处理路由键,只是简单地将队列绑定到交换器上.每个发送到交换器的消息都会被发送到与之绑定的所有队列上.广播模式,转发消息是最快的.
Topic Exchange:
topic交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上.它将路由键和绑定建的字符串切分成单词,这些单词之间用点隔开.
简言之就是匹配模式
4.springboot与rabbitmq的整合
整合大致分为这几步:
1.引入spring-boot-starter-amqp maven依赖
2.使用application.yml 进行参数配置
3.配置交换器与路由绑定
4.消息发布与接收
1.引入依赖
<dependencies>
<!-- web启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- rabbitmq所需依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
2.配置yml
spring:
application:
name: rabbitmq-provider
rabbitmq:
#用户名
username: admin
#密码
password: admin
#rabbitmq的服务端口
port: 5672
#ip
host: localhost
#vhost路径
virtual-host: /
listener:
simple:
acknowledge-mode: manual
server:
port: 8083
3 .配置路由,交换器并绑定
@Configuration
public class DirectRabbitmqConfig {
/** 创建Queue01队列*/
@Bean
public Queue getQueue01(){
//参数1 队列名
// 参数2 是否持久化
// 参数3 是否只能被当前创建的连接使用,并在连接关闭后销毁队列
// 参数4 是否在队列为空后自动销毁
//参数五5 其他配置信息
return new Queue("Queue01",true);
}
/** 创建Direct类型的交换器*/
@Bean
public DirectExchange getDirectExchange01(){
return new DirectExchange("DirectExchange01",true,true);
}
/** 将路由与交换器绑定*/
@Bean
public Binding bingQueueWithDirectExchange01(){
//将路由绑定到交换器并设置匹配键
return BindingBuilder.bind(getQueue01()).to(getDirectExchange01()).with("DirectRouting01");
}
}
4.消息的发布与接收
最后阶段,让我们编写接口进行消息的发布与接收.
@RestController
public class RabbitController {
@Autowired
private RabbitTemplate rabbitTemplate;
/** 使用rabbitTemplate 的send方法发送消息*/
@GetMapping("/sendMessage/{number}")
public ResponseEntity<String> sendMessage(@PathVariable("number") String number){
//指定消息类型
MessageProperties build = MessagePropertiesBuilder.newInstance().setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN).build();
//发送
rabbitTemplate.send("TestExchange1","TestQueue1",new Message(number.getBytes(StandardCharsets.UTF_8),build));
return ResponseEntity.ok("发送成功:"+number);
}
/** 使用rabbitTemplate 的convertAndSend方法发送消息*/
@GetMapping("/convertAndSendMessage/{number}")
public ResponseEntity<String> convertAndSendMessage(@PathVariable("number") String number){
rabbitTemplate.convertAndSend("TestExchange1","TestQueue1",number);
return ResponseEntity.ok("发送成功:"+number);
}
}
启动服务,访问服务路径
看到消息队列中已经就收到了消息.消息推送成功.
下面我们就编写代码去接收消息
创建监听类,监听指定队列
@Component
@RabbitListener(queues = {"Queue01"})
public class MyRabbitListener {
@RabbitHandler
public void accept(String message){
System.out.println("接收到消息:"+message);
}
}
再次重启服务
消息接收成功.
至此,rabbitmq与springboot的整合完成,其他类型exchange的api操作便不再多讲,小伙伴们自行研究.