RabbitMQ相关概念

在这里插入图片描述
其中包含几个概念
1. publisher生产者,也就是发送消息的一方
2. consumer消费者,也就是消费消息的一方
3. queue队列存储消息。生产者投递的消息会暂存在消息队列中等待消费者处理
4. exchange:交换机,负责消息路由生产者发送的消息由交换机决定投递到哪个队列
5. virtual host虚拟主机,起到数据隔离作用(相当于独立数据库)。每个虚拟主机相互独立,有各自的exchangequeue

Virtual host数据隔离

这里用户都是RabbitMQ的管理运维人员。目前只有安装RabbitMQ时添加itheima这个用户。仔细观察用户表格中的字段如下
在这里插入图片描述

对于小型企业而言,出于成本考虑我们通常只会搭建一套MQ集群公司内的多个不同项目同时使用这个时候为了避免互相干扰, 我们利用virtual host隔离特性,将不同项目隔离。一般会做两件事情:

创建用户hmall分配administrator权限
在这里插入图片描述
此时hmall用户没有任何virtual host访问权限
在这里插入图片描述
然后切换用户hmall进行登录,并给项目创建一个单独的virtual host,进行项目之间的隔离
在这里插入图片描述
由于我们是登录hmall账户后创建virtual host,因此回到users菜单,你会发现当前用户已经具备了对/hmall这个virtual host的访问权限了:
在这里插入图片描述
之前在virual host为/下创建队列、交换机就看不到了。

SpringAMQP

RabbitMQ官方提供的Java客户端编码相对复杂,一般生产环境下我们更多会结合Spring使用。而Spring官方刚好基于RabbitMQ提供了这样一套消息收发模板工具:SpringAMQP

第一种 基本消息模型

其实就是生产者将消息发送队列消费者从队列中取消息,队列存储消息的缓冲区(可以直接向队列发送消息,跳过交换机)——这种模式比较简单,很少在生产中使用
在这里插入图片描述

第二种 WorkQueues模型

Work queues任务模型。简单来说就是让多个消费者绑定一个队列,共同消费队列中的消息,主要处理消息堆积,可以使用work 模型,多个消费者共同处理消息,消息处理速度就能大大提高了。
在这里插入图片描述

spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1 # 每次只能获取一条消息,处理完成才能获取一个消息

三种 发布订阅模型(fanout交换机)

发布订阅模型,添加两个队列,分别各用一个消费者监听设置一个交换机,类型广播fanout),生产者将消息发送给交换机,而交换机将消息投递给所有与本交换机绑定(routingKey)的队列中
在这里插入图片描述
交换机只能转发消息,不能存储消息,有队列绑定转发到队列里,没有队列时候,交换机里的消息会立马丢失

fanout交换机实例

//发布订阅模式配置,包括两个队列和对应订阅者,发布者的交换机类型使用fanout(子网广播),两根网线binding用来绑定队列到交换机
@Configuration
public class FanoutExchangeConfig {

 	@Bean
    public Queue myQueue1() {
       Queue queue=new Queue("queue1");
       return queue;
    }
 	
 	@Bean
    public Queue myQueue2() {
       Queue queue=new Queue("queue2");
       return queue;
    }

	/**
	 * 声明交换机
	 */
	@Bean
 	public FanoutExchange fanoutExchange(){
 		FanoutExchange fanoutExchange=new FanoutExchange("fanout");
 		return fanoutExchange;
 	}
	/**
	 * 绑定队列到交换机上
	 */
 	@Bean
 	public Binding binding1(){
 		Binding binding=BindingBuilder.bind(myQueue1()).to(fanoutExchange());
 		return binding;
 	}
	/**
	 * 绑定队列2到交换机上
	 */
 	@Bean
 	public Binding binding2(){
 		Binding binding=BindingBuilder.bind(myQueue2()).to(fanoutExchange());
 		return binding;
 	}
 	
}

查看交换机
在这里插入图片描述
绑定到交换机下的队列
在这里插入图片描述

第四种 Direct交换机

在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在这里插入图片描述
在Direct模型下:

  • 队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key
  • 消息的发送方在 向 Exchange发送消息时,也必须指定消息的 RoutingKey。
  • Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

direct交换机实例

direct模式由于要绑定多个KEY,会非常麻烦,每一个Key都要编写一个binding

//direct直连模式的交换机配置,包括一个direct交换机,两个队列,4根网线binding
@Configuration
public class DirectExchangeConfig {
	@Bean
 	public DirectExchange directExchange(){
		DirectExchange directExchange=new DirectExchange("direct");
 		return directExchange;
 	}
	
	@Bean
    public Queue directQueue1() {
       Queue queue=new Queue("directqueue1");
       return queue;
    }
 	@Bean
    public Queue directQueue2() {
       Queue queue=new Queue("directqueue2");
       return queue;
    }
 	//4个binding将交换机和相应队列连起来
 	@Bean
 	public Binding bindingblack2(){
 		Binding binding=BindingBuilder.bind(directQueue1()).to(directExchange()).with("black");
 		return binding;
 	}
	@Bean
	public Binding bindingorange(){
		Binding binding=BindingBuilder.bind(directQueue1()).to(directExchange()).with("orange");
		return binding;
	}
 	@Bean
 	public Binding bindingblack(){
 		Binding binding=BindingBuilder.bind(directQueue2()).to(directExchange()).with("black");
 		return binding;
 	}
 	
 	@Bean
 	public Binding bindinggreen(){
 		Binding binding=BindingBuilder.bind(directQueue2()).to(directExchange()).with("green");
 		return binding;
 	}

}

基于注解方式声明——direct交换机

基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式声明

例如,我们同样声明Direct模式的交换机和队列:

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
    System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}
 
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue2"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
    System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

第五种Topic交换机

Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符
BindingKey 一般都是有一个或多个单词组成,多个单词之间以“ .”分割例如item.insert

通配符规则

  • #:匹配一个或多个词
  • *:匹配不多不少恰好1个词

举例:
item.#:能够匹配item.spu.insert 或者 item.spu
item.*:只能匹配item.spu

在这里插入图片描述

基于注解方式声明——Topic交换机

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue1"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "china.#"
))
public void listenTopicQueue1(String msg){
    System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}
 
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue2"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "#.news"
))
public void listenTopicQueue2(String msg){
    System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}

消息转换

数据传输时,它会把你发送的消息序列化字节发送给MQ,接收消息的时候,还会把字节序列化为Java对象。 只不过,默认情况下Spring采用序列化方式是JDK序列化。众所周知,JDK序列存在下列问题

配置JSON转换

显然,JDK序列化方式并不合适。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。

publisherconsumer两个服务中都引入依赖


<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.10</version>
</dependency>
@Bean
public MessageConverter messageConverter(){
    // 1.定义消息转换
    Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    // 2.配置自动创建消息id用于识别不同消息,也可以在业务基于ID判断是否是重复消息
    jackson2JsonMessageConverter.setCreateMessageIds(true);
    return jackson2JsonMessageConverter;
}

消息转换器中添加messageId可以便于我们将来做幂等性判断
consumer服务定义一个新的消费者,publisher是用什么类型发送,那么消费者也一定要用什么类型接收,格式如下

@RabbitListener(queues = "object.queue")
public void listenSimpleQueueMessage(Map<String, Object> msg) throws InterruptedException {
    System.out.println("消费者接收到object.queue消息:【" + msg + "】");
}

原文地址:https://blog.csdn.net/qq_44373419/article/details/134720955

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_30470.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注