RabbitMQ高级特性

1. 消息的可靠投递

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

RabbitMQ消息投递的路径(一般是):

producer—>rabbitmq broker—>exchange—>queue—>consumer

消息从 producer 到 exchange 则会返回一个 confirmCallback 。
消息从 exchange–>queue 投递失败则会返回一个 returnCallback 。

用代码展示具体的使用:
confirm确认模式:

		// 定义回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /*
            correlationData 相关配置信息
            ack: exchange交换机是否成功收到了消息 true 成功 false失败
            cause:失败的原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack) {
                    // 就收成功
                } else {
                    // 接受失败
                    // 做一些后续的处理
                }
            }
        });
        // 发送消息
        rabbitTemplate.convertAndSend("交换机", "路由", "发送的消息");

return 退回模式:

		// 回退模式:当消息发送给 exchange后,exchange路由到Queue失败时才会执行ReturnCallBack
        // 设置交换机处理失败消息的模式
        rabbitTemplate.setMandatory(true); // 将消息返给生产者

        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /*
            message 消息对象
            replyCode 错误码
            replyText 错误信息
            exchange 交换机
            routingKey 路由键
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange,
                String routingKey) {
                // 进行进一步处理
            }
        });
        // 发送消息
        rabbitTemplate.convertAndSend("交换机", "路由", "发送到消息");

总结:在使用这个是需要在yml文件里面配置相关属性

	#RabbitMQ的其他配置(地址,端口,账号,密码...)
    #开启确认模式
    publisher-confirms: true
    # 开启回退模式
    publisher-returns: true

在RabbitMQ中也提供了事务机制,但是性能较差,一般不使用,了解即可

txSelect(), 用于将当前channel设置成transaction模式
txCommit(),用于提交事务
txRollback(),用于回滚事务

		Connection connection = null;
        Channel channel = null;
        try {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            // 发送到消息
            String s = "发送的消息";
            // 绑定交换机
            channel.exchangeDeclare("交换机名称", "交换机类型", true); // 最后一个参数是说是否持久化
            // 声明队列
            channel.queueDeclare("队列名", true, true, false, null); // 第一个Boolean 是否持久化
             														//第二个Boolean 是否排外的 
             														//第三个Boolean 是否自动删除
                                                                 	// 第四个Map 队列中的消息什么时候会自动被删除?
            // 绑定队列
            channel.queueBind("队列名", "交换机名称", "路由键");

            channel.txSelect(); // 用于将当前channel设置成transaction模式
            channel.basicPublish("交换机名称",
             						"路由键", 
            						 true,
              						com.rabbitmq.client.MessageProperties.MINIMAL_BASIC,
                					s.getBytes());
            channel.txCommit(); // 用于提交事务
        } catch (Exception e) {
            channel.txRollback(); // 用于回滚事务
        } finally {
            // 关闭连接 关闭信道
        }

2. 消费者 Acknowledge

Acknowledge表示消费者收到消息后的确认方式。一共有三种:

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

自动确认方式是指,当消息一旦被Consumer接收到,则自动确认收到,并将相应 message 从 RabbitMQ 的消息缓存中移除。但是在实际业务处理中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失。
手动确认方式,则需要在业务处理成功后,调用channel.basicAck(),手动签收,如果出现异常,则调用channel.basicNack()方法,让其自动重新发送消息。

在使用这个是需要在yml文件里面配置相关属性

listener:
  simple:
    acknowledge-mode: manual # manual为手动确认 none为自动确认 auto根据异常情况确认
@RabbitListener(queuesToDeclare = @Queue("${队列全路径名}"))
    public void receiveMessage(Message message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag)
        throws Exception {
        try {
            // 就收message消息
            String s = new String(message.getBody());
            // 处理逻辑
            channel.basicAck(tag, true); // Boolean类型multiple 如果设置为true,一条消息应答了,那么之前的全部消息将被应答。
                                         // 比如目前channel中有delivery tags为5,6,7,8的消息,那么一旦8被应答,那么5,6,7将都被应答;
                                         // 如果设置为false,那么5,6,7将不会被应答。
        } catch (Exception e) {
            channel.basicNack(tag,true,true); // 第二个Boolean 如果为true表示重新回到队列,反之
            //channel.basicReject(tag,true);
        }
    }

3. 消息可靠性总结

持久化( exchange要持久化 queue要持久化 message要持久化 )

生产方确认Confirm

消费方确认Ack

Broker高可用

4. 消费端限流

在这里插入图片描述
配置如下就可以对读取MQ里面的数据进行限流

listener:
      simple:
        #限流
        prefetch: 1 #配置每次接受条数即可

5. TTL

TTL 全称 Time To Live(存活时间/过期时间)。
当消息到达存活时间后,还没有被消费,会被自动清除。
RabbitMQ可以对消息设置过期时间,也可以对整个队列(Queue)设置过期时间。

在发送消息的时候,对消息设置如下代码:

//1.设置message的信息
 message.getMessageProperties().setExpiration("5000");//消息的过期时间 5s过期

6. 死信队列

死信队列,英文缩写:DLX 。
Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。
在这里插入图片描述
一条消息成为死信一共有三种情况:

  1. 队列里面的消息达到队列长度极限;
  2. 消费者拒绝接受消息,并且不会到原来队列;(BasicNack/basicReject 方法的queue参数为flase);
  3. 原队列当中设置了消息过期时间,消息已经过期。

将原队列与死信交换机进行绑定:
在这里插入图片描述
具体代码如下:

/**
     * 为队列绑定死信队列
     * @return
     */
    @Bean
    public Queue queueA() {
    	Map<String, Object> args = new HashMap<>(3);
        //声明死信交换器
        args.put("x-dead-letter-exchange", "dlx.exchange");
        //声明死信路由键
        args.put("x-dead-letter-routing-key", ROUTINGKEY_A );
        //声明队列消息过期时间 30分钟
        args.put("x-message-ttl", 1800000);
//        args.put("x-message-ttl", 10000);
        return new Queue(QUEUE_A, true, false, false, args);//队列持久
        }

7. 延迟队列

概念:即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。
使用场景:

  • 下单后,30分钟未支付,取消订单,回滚库存。
  • 新用户注册成功7天后,发送短信问候。
    在这里插入图片描述
    但是MQ并没有提供延迟队列这种类型,我们需要通过死信队列+TTL来实现。
    在这里插入图片描述
@Bean
    public Queue payQueue(){
        Map<String,Object> params = new HashMap<>();
        //设置队列的过期时间
        params.put(ttl,10000);
        //声明当前队列绑定的死信交换机
        params.put(dle,dlTopicExchange);
        //声明当前队列的死信路由键
        params.put(dlk,dlRoutingKey);
        return QueueBuilder.durable(queueName).withArguments(params).build();
    }

8.日志与监控

通过UI界面可以看到每一个队列的具体信息;此处不详细解说。

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值