文章目录
- 1 交换器
- 1.1 Direct 交换器
- 1.1.1 使用需求
- 1.1.2 Consumer消费者
- 1.1.2.1 properties配置文件
- 1.1.2.2 消费者实体类
- 1.1.3 Provider提供者
- 1.1.3.1 properties配置文件
- 1.1.3.2 生产消息实体
- 1.1.3.3 测试类
- 1.2 Topic 交换器
- 1.2.1 使用需求
- 1.2.2 Consumer消费者
- 1.2.2.1 properties配置文件
- 1.2.2.2 消费者实体类
- 1.2.3 Provider提供者
- 1.2.3.1 properties配置文件
- 1.2.3.2 生产消息类实体
- 1.3 Fanout 交换器
- 1.3.1 需求
- 1.3.2 Consumer消费者
- 1.3.2.1 配置文件
- 1.3.2.2 消费者实体类
- 1.3.3 provider生产者
- 1.3.3.1 配置文件
- 1.3.3.2 生产者实体类
- 1.4 RabbitMQ的消息持久化处理
1 交换器
用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
三种常用的交换器类型:
-
direct
(发布与订阅 完全匹配) -
topic
(主题, 规则匹配) -
fanout
(广播)附
:这三个交换器都用这个坐标
<!-- RabbitMQ的maven坐标 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
1.1 Direct 交换器
Direct
交换器发布与订阅 完全匹配
1.1.1 使用需求
系统日志处理场景
- 微服务产生的日志,交给日志处理器处理
- 日志处理服务器有
2
个服务,分别为info,error
- 服务的直接通信采用
direct
(发布订阅)
1.1.2 Consumer消费者
1.1.2.1 properties配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
####这些都是自定义的属性名#######
# 设置交换器名称
mq.config.exchange=log.direct
#设置info队列名称
mq.config.queue.info=log.info
#设置info路由名称
mq.config.queue.info.routing.key=log.info.routing.key
#设置error队列名称
mq.config.queue.error=log.error
#设置error路由名称
mq.config.queue.error.routing.key=log.error.routing.key
1.1.2.2 消费者实体类
@RabbitListener
- 属性:
bindings
:绑定队列
- 注解
@QueueBinding
- 属性:
value
:绑定队列的名称 (注解@Queue
:value
:配置队列名称,autoDelete
:是否是一个可删除的临时队列) - 属性:
exchange
:配置交换器(@Exchange
:value
·:为交换器起个名称,type
:指定具体的交换器类型) - 属性:
key
:路由键
@Component
@RabbitListener(
bindings =
@QueueBinding(value = @Queue(value = "${mq.config.queue.error}", autoDelete = "true"),
exchange = @Exchange(value = "${mq.config.exchange}", type = ExchangeTypes.DIRECT),
key = "${mq.config.queue.error.routing.key}")
)
public class ErrorReceiver {
/**
* 接收消息的方法 采用消息队列监听机制
*/
@RabbitHandler
public void process(String msg) {
System.out.println("error........." + msg);
}
}
1.1.3 Provider提供者
1.1.3.1 properties配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
##########此处的名字是自己随意定义的############
# 设置交换器名称
mq.config.exchange=log.direct
#设置info队列名称
mq.config.queue.info=log.info
#设置info路由名称
mq.config.queue.info.routing.key=log.info.routing.key
#设置error队列名称
mq.config.queue.error=log.error
#设置error路由名称
mq.config.queue.error.routing.key=log.error.routing.key
### 此处名字是rabbitmq的,不是自定义的,下面两个属性是为了怕连不上,而设置的重试
# 是否打开重试次数
spring.rabbitmq.listener.simple.retry.enabled=true
# 设置rabbitmq最大重试次数
spring.rabbitmq.listener.simple.retry.max-attempts=5
1.1.3.2 生产消息实体
@Component
public class SenderDemo {
@Autowired
private AmqpTemplate template;
//交换器名称
@Value("${mq.config.exchange}")
private String exchange;
//路由键
@Value("${mq.config.queue.info.routing.key}")
private String routingKey;
/**
* 发送消息
*/
public void send (String msg) {
//参数一:交换器名称
//参数二:路由键名称
//参数三:消息
this.template.convertAndSend(this.exchange,this.routingKey,msg);
}
}
1.1.3.3 测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes=AppAction.class)
public class TestSenderDemo {
@Autowired
private SenderDemo sender;
@Test
public void testSend() throws InterruptedException {
int flag=0;
while(true) {
flag++;
Thread.sleep(2000);
System.out.println(flag);
this.sender.send("Hello RabbitMQ============="+flag);
}
}
}
1.2 Topic 交换器
Topic
交换器,主题, 规则匹配,即模糊匹配
1.2.1 使用需求
1.2.2 Consumer消费者
1.2.2.1 properties配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
# 设置交换器名称
mq.config.exchange=log.topic
#设置info队列名称
mq.config.queue.info=log.info
#设置error队列名称
mq.config.queue.error=log.error
#log 队列名称
mq.config.queue.logs=log.all
1.2.2.2 消费者实体类
@RabbitListener
- 属性:
bindings
:绑定队列
- 注解
@QueueBinding
- 属性:
value
:绑定队列的名称 (注解@Queue
:value
:配置队列名称,autoDelete
:是否是一个可删除的临时队列) - 属性:
exchange
:配置交换器(@Exchange
:value
·:为交换器起个名称,type
:指定具体的交换器类型) - 属性:
key
:路由键InfoReceiver.java
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.info}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.info"
)
)
public class InfoReceiver {
/**
* 接收消息的方法。 采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......Info........receiver:"+msg);
}
ErrorReceiver.java
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.error}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.error"
)
)
public class ErrorReceiver {
@RabbitHandler
public void process(String msg){
System.out.println("......Error........receiver:"+msg);
}
}
LogsReceiver.java
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.logs}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.*"
)
)
public class LogsReceiver {
@RabbitHandler
public void process(String msg){
System.out.println("......All........receiver:"+msg);
}
}
1.2.3 Provider提供者
1.2.3.1 properties配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
#设置交换器的名称
mq.config.exchange=log.topic
1.2.3.2 生产消息类实体
UserSender.java
@Component
public class UserSender {
@Autowired
private AmqpTemplate rabbitAmqpTemplate;
//exchange 交换器名称
@Value("${mq.config.exchange}")
private String exchange;
/*
* 发送消息的方法
*/
public void send(String msg){
//向消息队列发送消息
//参数一: 交换器名称。
//参数二: 路由键
//参数三: 消息
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"user.log.debug", "user.log.debug....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"user.log.info", "user.log.info....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"user.log.warn","user.log.warn....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"user.log.error", "user.log.error....."+msg);
}
}
ProductSender
类
@Component
public class ProductSender {
@Autowired
private AmqpTemplate rabbitAmqpTemplate;
//exchange 交换器名称
@Value("${mq.config.exchange}")
private String exchange;
/*
* 发送消息的方法
*/
public void send(String msg){
//向消息队列发送消息
//参数一: 交换器名称。
//参数二: 路由键
//参数三: 消息
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"product.log.debug", "product.log.debug....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"product.log.info","product.log.info....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"product.log.warn","product.log.warn....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"product.log.error", "product.log.error....."+msg);
}
}
OrderSender
@Component
public class OrderSender {
@Autowired
private AmqpTemplate rabbitAmqpTemplate;
//exchange 交换器名称
@Value("${mq.config.exchange}")
private String exchange;
/*
* 发送消息的方法
*/
public void send(String msg){
//向消息队列发送消息
//参数一: 交换器名称。
//参数二: 路由键
//参数三: 消息
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"order.log.debug", "order.log.debug....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"order.log.info", "order.log.info....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"order.log.warn","order.log.warn....."+msg);
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"order.log.error", "order.log.error....."+msg);
}
}
测试方法同1.1.3.3
测试类,故不再赘述
1.3 Fanout 交换器
Fanout
交换器就是同步变异步,所有的队列都要发送,因此不需要路由键了
1.3.1 需求
1.3.2 Consumer消费者
1.3.2.1 配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
#设置交换器的名称
mq.config.exchange=order.fanout
#短信服务队列名称
mq.config.queue.sms=order.sms
#push 服务队列名称
mq.config.queue.push=order.push
1.3.2.2 消费者实体类
@RabbitListener
- 属性:
bindings
:绑定队列
- 注解
@QueueBinding
- 属性:
value
:绑定队列的名称 (注解@Queue
:value
:配置队列名称,autoDelete
:是否是一个可删除的临时队列) - 属性:
exchange
:配置交换器(@Exchange
:value
·:为交换器起个名称,type
:指定具体的交换器类型) - 属性:
key
:路由键,因为是广播模式,所以不需要路由键SmsReceiver.java
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.sms}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.FANOUT)
)
)
public class SmsReceiver {
@RabbitHandler
public void process(String msg){
System.out.println("Sms........receiver: "+msg);
}
}
PushReceiver.java
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.push}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.FANOUT)
)
)
public class PushReceiver {
@RabbitHandler
public void process(String msg){
System.out.println("Push..........receiver: "+msg);
}
}
1.3.3 provider生产者
1.3.3.1 配置文件
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=rabbitmq
# RabbitMQ的密码
spring.rabbitmq.password=123456
#设置交换器的名称
mq.config.exchange=order.fanout
1.3.3.2 生产者实体类
因为是广播模式,所以路由键是空字符串
@Component
public class Sender {
@Autowired
private AmqpTemplate rabbitAmqpTemplate;
//exchange 交换器名称
@Value("${mq.config.exchange}")
private String exchange;
/*
* 发送消息的方法
*/
public void send(String msg){
//向消息队列发送消息
//参数一: 交换器名称。
//参数二: 路由键 因为广播模式,所以路由键是空字符串
//参数三: 消息
this.rabbitAmqpTemplate.convertAndSend(this.exchange,"",msg);
}
}
1.4 RabbitMQ的消息持久化处理
消息的可靠性是 RabbitMQ
的一大特色, 那么 RabbitMQ
是如何保证消息可靠性的呢——消息持久化,主要通过在消息接收者上的注解@RabbitListener
修改内部属性。
-
@Queue
属性中的autoDelete
: 当所有消费客户端连接断开后, 是否自动删除队列true
: 删除false
: 不删除,默认为空字符串 -
@Exchange
属性中的autoDelete
: 当所有绑定队列都不在使用时, 是否自动删除交换器true
: 删除false
: 不删除,默认为false
如下为@RabbitListener
的内部属性:
- 属性:
bindings
:绑定队列
- 注解
@QueueBinding
- 属性:
value
:绑定队列的名称 (注解@Queue
:value
:配置队列名称,autoDelete
:是否是一个可删除的临时队列) - 属性:
exchange
:配置交换器(@Exchange
:value
·:为交换器起个名称,type
:指定具体的交换器类型) - 属性:
key
:路由键