微服务框架 SpringCloud微服务架构 服务异步通讯 50 消息可靠性 50.4 失败重试机制 50.4.2 消费者失败消息处理策略 & 50.4.3 总结

本文详细介绍了在SpringCloud微服务架构中,结合RabbitMQ实现消息的可靠传递。重点讨论了消息失败重试机制,特别是RepublishMessageRecoverer的使用,它在消息处理失败后将消息转发到特定交换机,供错误处理消费者进行后续操作。通过配置RepublishMessageRecoverer,确保了消息在多次重试后仍能被正确处理,增强了系统的容错能力。

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

微服务框架

【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】

服务异步通讯

50 消息可靠性

50.4 失败重试机制
50.4.2 消费者失败消息处理策略

在开启重试模式后,重试次数耗尽,如果消息依然失败,则需要有MessageRecoverer接口来处理,它包含三种不同的实现:

  • RejectAndDontRequeueRecoverer:重试耗尽后,直接reject,丢弃消息。【默认】就是这种方式
  • ImmediateRequeueMessageRecoverer:重试耗尽后,返回nack,消息重新入队
  • RepublishMessageRecoverer:重试耗尽后,将失败消息投递到指定的交换机【相当于重发】

【举个栗子】

在这里插入图片描述

这就是一个普通的模型结构

在这里插入图片描述

现在生产者 发送了一条消息,经过交换机、队列到达了消费者,但是在消费者 处理的时候失败了 ,然后它就多次重试

在这里插入图片描述

直到 重试资源 耗尽

按照以前的方式,要么直接丢了,要么就是重新回到队列

RepublishMessageRecoverer 这种方案 会准备一个新的交换机

在这里插入图片描述

这个交换机专门用于接收失败消息,

在这里插入图片描述

重试资源耗尽后, 消费者就会将消息 投递给这个交换机,光有交换机不够,因为交换机只是用来转发消息,然后现在还得有 一个队列

在这里插入图片描述

这样投递到这个交换机的消息最终一定会进入 error.queue 这个队列中

在这里插入图片描述

然后就可以专门搞一个消费者 去监听这个error.queue 队列【兜底方案】

【如何实现?】

测试下RepublishMessageRecoverer处理模式:

  • 首先,定义接收失败消息的交换机、队列及其绑定关系:

在这里插入图片描述

来一个新的配置类

package cn.itcast.mq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * ClassName: ErrorMessageConfig
 * date: 2022/11/9 18:53
 *
 * @author DingJiaxiong
 */

@Configuration
public class ErrorMessageConfig {

    // error 交换机
    @Bean
    public DirectExchange errorMessageExchange(){

        return new DirectExchange("error.direct");
    }

    //队列
    @Bean
    public Queue errorQueue(){

        return new Queue("error.queue");
    }

    //绑定
    @Bean
    public Binding errorMessageBinding(){

        return BindingBuilder.bind(errorQueue()).to(errorMessageExchange()).with("error");
    }

    @Bean
    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){

        return new RepublishMessageRecoverer(rabbitTemplate,"error.direct","error");
    }

}
  • 然后,定义RepublishMessageRecoverer:

在这里插入图片描述

直接重启测试

在这里插入图片描述

OK, 重启完成

查看控制台

在这里插入图片描述

OK, 队列创建好了

在这里插入图片描述

交换机也创建好了, 关系也绑上 了

向simple.queue 发送一条消息

在这里插入图片描述

直接发送

在这里插入图片描述

查看IDEA 控制台日志

在这里插入图片描述

这次重试资源用完后,没有报错,说消息转发了

再次查看MQ 控制台

在这里插入图片描述

没毛病

在这里插入图片描述

而且,这条消息,不仅有,还把 异常的栈信息带过来了

牛逼!!!!!!!!

50.4.3 总结

如何确保RabbitMQ消息的可靠性?

  • 开启生产者确认机制,确保生产者的消息能到达队列
  • 开启持久化功能,确保消息未消费前在队列中不会丢失
  • 开启消费者确认机制为auto,由spring确认消息处理成功后完成ack
  • 开启消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理
在C语言中,我们可以使用冒泡排序算法对整型数组或浮点数组进行排序。对于给定的数值 (70, 60.01, 80.90, 2, 50.4),由于包含了整数和浮点数,我们首先需要明确这个数据结构应该是一个混合数组还是分开存储。假设这是一个混合数组,我们可以将其视为元组,然后将每个元素看作单独的值进行排序。下面是使用冒泡排序的一个示例: ```c #include <stdio.h> void bubble_sort(int *arr, int size, int* is_float) { for (int i = 0; i < size - 1; i++) { for (int j = 0; j < size - 1 - i; j++) { // 比较整数部分 if (*(is_float + j) && *(is_float + j+1)) { // 如果相邻的是浮点数,比较它们的数值 if (*(arr + j) > *(arr + j+1)) { // 交换位置 double temp = *(arr + j); *(arr + j) = *(arr + j+1); *(arr + j+1) = temp; } } else if (!*(is_float + j) && *(is_float + j+1)) { // 如果一个是整数一个是浮点数,先比较整数 if (*(arr + j) > *(arr + j+1)) { int temp = *(arr + j); *(arr + j) = *(arr + j+1); *(arr + j+1) = temp; } } else if (*(is_float + j) && !*(is_float + j+1)) { // 同理,如果一个是浮点数一个是整数 if (*(double *)(arr + j) > *(int*)(arr + j+1)) { // 转换并比较 int temp_int = *(int*)(arr + j); *(arr + j) = *(int*)(arr + j+1); *(arr + j+1) = temp_int; } } } } } int main() { int arr[] = {70, 60, 0, 80, 90, 2}; int is_float[6] = {0, 1, 0, 1, 0, 1}; // 标记哪些元素是浮点数 int size = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, size, is_float); for (int i = 0; i < size; i++) { if (is_float[i]) { printf("%.2f ", arr[i]); } else { printf("%d ", arr[i]); } } return 0; } ``` 在这个例子中,`is_float` 数组用于标记每个元素是否为浮点数。注意,C语言本身并不支持直接混合类型数组,所以这里假设了每个元素都有对应的标记。在实际应用中,这可能会根据具体的内存分配和处理方式进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祝我天天开心,平安健康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值