RabbitMQ常用3种交换器详解

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:绑定队列的名称 (注解@Queuevalue:配置队列名称,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:绑定队列的名称 (注解@Queuevalue:配置队列名称,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:绑定队列的名称 (注解@Queuevalue:配置队列名称,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修改内部属性。

  1. @Queue属性中的autoDelete: 当所有消费客户端连接断开后, 是否自动删除队列 true: 删除 false: 不删除,默认为空字符串
  2. @Exchange属性中的autoDelete: 当所有绑定队列都不在使用时, 是否自动删除交换器true: 删除 false: 不删除,默认为false

如下为@RabbitListener 的内部属性:

  • 属性:bindings:绑定队列
    • 注解@QueueBinding
      • 属性:value:绑定队列的名称 (注解@Queuevalue:配置队列名称,autoDelete:是否是一个可删除的临时队列)
      • 属性:exchange:配置交换器(@Exchange :value·:为交换器起个名称,type:指定具体的交换器类型)
      • 属性:key:路由键
发布了334 篇原创文章 · 获赞 186 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/u012060033/article/details/104258895