RabbitMQ 知识点

本文详细介绍RabbitMQ消息中间件的工作原理及其应用场景,包括消息队列、交换机、工作队列模式、发布订阅模式等概念,并深入探讨消息的可靠投递、消费确认、消费者限流、TTL存活时间、死信队列、延迟队列等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RabbitMQ 知识点

1.什么是消息中间件?

MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高系统吞吐量

MQ的主要优点:
应用解耦——增加整个系统的隔离性和扩展性,让各个系统之间耦合性降低,可以分别维护。
异步提速——不使用MQ前,各个系统互相同步调用,需要将全部运行完毕后才可以响应前端,而使用MQ作为中间件相当于一个阻塞队列,实现异步响应,大大提高前端的响应时间,将后台数据异步处理。
削峰填谷——活动期间,大量请求接入服务器将对服务器造成很大压力,而采用MQ作为缓冲器,让服务器从中持续处理请求,可以平均服务器压力。

主要缺点:
引入了MQ中间件,降低了系统的稳定性,如果MQ挂了,业务也会停掉
提高了复杂度,需要处理详细重复消费,丢失,顺序性等幂等性问题
一致性问题,同时通过MQ发向多个消费者,如果一个消费者挂了,其他成功了,怎么保证消息的一致呢?

总结:MQ适用于:生产者不需要消费者的及时反馈,即消息对自己本身不造成影响、同时允许不一致性,允许各系统数据短暂不一致。

2.生产者和消费者

生产者:
1.创建ConnectFactory 并设置地址和账户参数
2.使用ConnectFactory对象创建一个频道Channel
3.设置channel参数:队列名称,是否定义持久化队列,是否独占本次连接,是否在不使用的时候自动删除队列,队列其它参数(map)
4. channel.basicPublish方法 生产消息 参数:交换机名称,如果没有指定则使用默认Default Exchage,路由key,简单模式可以传递队列名称,消息其它属性,消息内容

消费者
1.用同样的队列建立channel对象
2.建立一个消费者对象,用于配置消费者
3.重写 handleDelivery方法用于处理消息
4.使用channel.basicConsume方法启动消费者监听

 		//建立连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.146.129");
        factory.setPort(5672);
        factory.setVirtualHost("/jiaxinger");
        factory.setUsername("wannibaba172");
        factory.setPassword("wannibaba172");
           //建立频道
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
            AMQP.Queue.DeclareOk queue = channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            //生产消息
            channel.basicPublish("",QUEUE_NAME,null,"hey!guys!".getBytes());
            System.out.println("消息已发送");
            channel.close();
            connection.close();
	 try {
            Channel channel = RabbitMqConnectionUtil.getChannel();
            channel.queueDeclare("simple_queue", true, false, false, null);
            //创建一个消费者对象
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                /**
                 * consumerTag 消息者标签,在channel.basicConsume时候可以指定
                 * envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志(收到消息失败后是否需要重新发送)
                 * properties 属性信息
                 * body 消息
                 */
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //路由key
                    System.out.println("路由key为:" + envelope.getRoutingKey());
                    //交换机
                    System.out.println("交换机为:" + envelope.getExchange());
                    //消息id
                    System.out.println("消息id为:" + envelope.getDeliveryTag());
                    //收到的消息
                    System.out.println("接收到的消息为:" + new String(body, "utf-8"));
                }
            };

            String s = channel.basicConsume("simple_queue", consumer);
            System.out.println(s);

3.工作模式

  1. Work queues工作队列模式
    多个消费者消费一个队列中的消息,用于分发工作,提高任务处理速度。

  2. 订阅模式类型
    订阅模式中开始启用交换机exchange了,生产者对队列发送消息,再由交换机进行转发处理,交换机通常分为三种类型:

  • Fanout:广播,将消息交给所有绑定到交换机的队列

  • Direct:定向,把消息交给符合指定routing key 的队列

  • Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列

    交换机负责对消息进行转发,如果没有标的,将会丢失信息。实际上如果不指定交换机的情况下,会使用默认交换机的。

//声明和绑定示例
 Channel channel = RabbitMqConnectionUtil.getChannel();
            channel.exchangeDeclare("simple_exchange", BuiltinExchangeType.FANOUT);
            channel.queueDeclare("simple_queue2", true, false, false, null);
            channel.queueBind("simple_queue2","simple_exchange","");
  1. Routing路由模式
    在绑定交换机的时候绑定routing key就代表路由模式,在路由模式下Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

  2. Topics通配符模式
    Topic类型与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符

通配符规则:
#:匹配一个或多个词
*:匹配不多不少恰好1个词
.:每个单词用.来进行分割

模式总结

RabbitMQ工作模式:
1、简单模式 HelloWorld
一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)

2、工作队列模式 Work Queue
一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)

3、发布订阅模式 Publish/subscribe
需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列

4、路由模式 Routing
需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

5、通配符模式 Topic
需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

4.消息的可靠投递

在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。
confirm 确认模式
return 退回模式

rabbitmq 整个消息投递的路径为:
producer—>rabbitmq broker—>exchange—>queue—>consumer
消息从 producer 到 exchange 则会返回一个 confirmCallback 。
消息从 exchange–>queue 投递失败则会返回一个 returnCallback 。

在rabbitMQ的参数中设置开启可靠投递

spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true

调用RabbitMQTemplate里的setConfirmCallback和setReturnCallback设置回调函数

4.消息的消费确认ack

自动确认:acknowledge=“none”
手动确认:acknowledge=“manual”
根据异常情况确认:acknowledge=“auto”

使用手动接受:
设置ack模式为手动:

  listener:
      direct:
        acknowledge-mode: none

在编写的RabbitListener类中调用channel.basicAck方法设置确认函数
调用channel.Nack方法设置返回函数
实例:

 try {
            System.out.println("Listener get message"+message.getBody());
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
            System.out.println("消息接受成功");
        } catch (IOException e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),true,true);
            System.out.println("消息被返回");
        }

5.消费者限流

为了避免消费者拉取过多消息而挂掉,我们应该设置拉取消息的最大值
而配置prefetch: 属性则可以设置消费者在确认先可以拉取多少条消息,避免消费者压力过大。

6.TTL 存活时间

在配置queue时设置ttl属性或设置ttl方法可以添加消息存活时间,到底定时过期消息的目的
设置队列存活时间,整个队列的消息会在时间内同时过期

public Queue getQueue1(){
       return QueueBuilder.durable("queue3").ttl(10000).build();

单独设置消息过期时间:

 rabbitTemplate.convertAndSend("Exchange", "first", "运行测试中..." + i, new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setExpiration("5000");
                    return message;
                }

7.DLX 死信队列

死信队列就是一个专门用来回收消息的队列,它本质上和普通的队列没有区别,只是用途上有所不同。
消息成为死信的三种情况:

  1. 队列消息长度到达限制;
  2. 消费者拒接消费消息,并且不重回队列;
  3. 原队列存在消息过期设置,消息到达超时时间未被消费;

给队列设置参数: x-dead-letter-exchange 和 x-dead-letter-routing-key

8.延迟队列

延迟队列的消息只有到达指定时间才能被消费
比如:30分钟后未支付取消订单

使用TTL+死信队列实现延迟队列
即设置一个TTL队列,如果消息超时进入死信队列,则由死信监听器进行业务回滚。

9.rabbitMQ消息追踪

开启消息追踪后会将生产的消息进行一个备份转发,发送到默认的trace,可以用来追踪消息的传递情况
rabbitmqctl trace_on:开启Firehose命令

rabbitmqctl trace_off:关闭Firehose命令

也可以启用插件:rabbitmq-plugins enable rabbitmq_tracing,在rabbitmq的控制台网页使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值