RabbitMQ队列,2024火爆全网系列

启动它消费死信队列

image-20240302111857175

消费完成,看看管理界面,死信消息归0

image-20240302111933926

1.5、队列达到最大长度的死信

​ 在原来的消费者基础上增加一条

//设置队列最大长度
arguments.put(“x-max-length”,6);

​ 原来的生产者也不需要给消息设置过期时间了直接发送消息即可。

​ 测试之前先将原来的普通队列删除再启动消费者

image-20240302134737969

​ 仍然把消费者停掉,生产者启动,发送10条消息6条正常4条超过了限制会被放到死信队列

image-20240302134915165

1.6、消息被拒死信队列

我们先把原来的消息全部消费掉或者直接删除原来的队列,再演示新的。

消费者做一些修改

DeliverCallback deliverCallback = (consumerTag,message) ->{
String msg = new String(message.getBody());
if (msg.equals(“dead5”)){
System.out.println(“拒绝第5个消息:”+ msg);
//basicReject第二个参数是是否还放回队列
channel.basicReject(message.getEnvelope().getDeliveryTag(),false);
} else {
System.out.println(“死信测试普通队列消费者01收到消息:” + msg);
channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
}

};
channel.basicConsume(NORMAL_QUEUE,false,deliverCallback,consumerTag -> {});

生产者发送10条消息,看到消费者01拒绝了第5个消息,其他的正常收到

image-20240302143440745

通过管理界面看到第5条消息放到了死信队列中

image-20240302143507611

启动专门消费死信队列的消费者02将第5个消息消费。

image-20240302143537357

2、延迟队列

2.1、延迟队列概念

​ 延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。

其实,TTL过期导致的死信队列就是延迟队列

应用场景:

  • 1.订单在十分钟之内未支付则自动取消
  • ⒉新创建的店铺,如果在十天内都没有上传过商品,则自动发送消息提醒。
  • 3.用户注册成功后,如果三天内没有登陆则进行短信提醒。
  • 4.用户发起退款,如果三天内没有得到处理则通知相关运营人员。
  • 5.预定会议后,需要在预定的时间点前十分钟通知各个与会人员参加会议

​ 这些场景都有一个特点,需要在某个事件发生之后或者之前的指定时间点完成某一项任务,如:发生订单生成事件,在十分钟之后检查该订单支付状态,然后将未支付的订单进行关闭;看起来似乎使用定时任务,一直轮询数据,每秒查一次,取出需要被处理的数据,然后处理不就完事了吗?

​ 如果数据量比较少,确实可以这样做,比如:对于“如果账单一周内未支付则进行自动结算”这样的需求,如果对于时间不是严格限制,而是宽松意义上的一周,那么每天晚上跑个定时任务检查一下所有未支付的账单,确实也是一个可行的方案。

​ 但对于数据量比较大,并且时效性较强的场景,如:“订单十分钟内未支付则关闭“,短期内未支付的订单数据可能会有很多,活动期间甚至会达到百万甚至千万级别,对这么庞大的数据量仍旧使用轮询的方式显然是不可取的,很可能在一秒内无法完成所有订单的检查,同时会给数据库带来很大压力,无法满足业务要求而且性能低下。

2.1.1、RabbitMQ 中的 TTL

​ TTL 是什么呢?TTL 是 RabbitMQ 中一个消息或者队列的属性,表明一条消息或者该队列中的所有 消息的最大存活时间, 单位是毫秒。

​ 换句话说,如果一条消息设置了 TTL 属性或者进入了设置 TTL 属性的队列,那么这 条消息如果在 TTL 设置的时间内没有被消费,则会成为"死信"。如果同时配置了队列的 TTL 和消息的 TTL,那么较小的那个值将会被使用,有两种方式设置 TTL。

  • 消息设置 TTL

例如:

rabbitTemplate.convertAndSend(“X”,“XC”,message,msg -> {
//发送消息设置消息的TTL
msg.getMessageProperties().setExpiration(ttl+“000”);
return msg;
});

  • **队列设置 TTL **

例如:在创建队列的时候设置队列的“x-message-ttl”属性

//声明普通队列 TTL 为40秒
@Bean(“queueB”)
public Queue queueB(){
HashMap<String, Object> map = new HashMap<>(3);
//设置死信交换机
map.put(“x-dead-letter-exchange”,Y_DEAD_LETTER_EXCHANGE);
//设置死信RoutingKey
map.put(“x-dead-letter-routing-key”,“YD”);
//设置过期时间,10秒
map.put(“x-message-ttl”,40000);
return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}

2.2、整合SpringBoot

添加依赖项

org.springframework.boot spring-boot-starter-amqp ${spring.boot.version} org.springframework.boot spring-boot-starter-web ${spring.boot.version} org.springframework.boot spring-boot-starter-test ${spring.boot.version} test com.taobao.arthas fastjson 1.2.80-fix org.projectlombok lombok ${lombok.version} io.springfox springfox-swagger2 ${springfox.version} io.springfox springfox-swagger-ui ${springfox.version} org.springframework.amqp spring-rabbit-test ${spring.amqp.version} test org.springframework.boot spring-boot-maven-plugin

创建application.properties文件

spring.rabbitmq.host=192.168.111.28
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.redis.password=123

swagger2的配置类SwaggerConfig

@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket webApiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“webApi”)
.apiInfo(webApiInfo())
.select()
.build();
}
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title(“rabbitmq 接口文档”)
.description(“本文档描述了 rabbitmq 微服务接口定义”)
.version(“1.0”)
.contact(new Contact(“zm”, “http://zmblog.vip”,
“3339332352@qq.com”))
.build();
}
}

2.3、队列TTL

​ 创建两个队列 QA 和 QB,两者队列 TTL 分别设置为 10S 和 40S,然后在创建一个交换机 X 和死信交 换机 Y,它们的类型都是 direct,创建一个死信队列 QD,它们的绑定关系如下:

image-20240302163555580

2.4、配置文件类代码

TtlQueueConfig

//TTL队列,配置类代码
@Configuration
public class TtlQueueConfig {
//普通交换机名称
public static final String X_EXCHANGE = “X”;
//死信交换机名称
public static final String Y_DEAD_LETTER_EXCHANGE = “Y”;
//普通队列名称,两个
public static final String QUEUE_A = “QA”;
public static final String QUEUE_B = “QB”;
//死信队列名称
public static final String DEAD_LETTER_QUEUE = “QD”;

//声明普通交换机X_EXCHANGE,起一个别明xExchange注入bean
@Bean(“xExchange”)
public DirectExchange xExchange(){
return new DirectExchange(X_EXCHANGE);
}
//声明死信交换机Y_EXCHANGE,起一个别明yExchange注入bean
@Bean(“yExchange”)
public DirectExchange yExchange(){
return new DirectExchange(Y_DEAD_LETTER_EXCHANGE);
}
//声明普通队列 TTL 为10秒
@Bean(“queueA”)
public Queue queueA(){
HashMap<String, Object> map = new HashMap<>(3);
//设置死信交换机
map.put(“x-dead-letter-exchange”,Y_DEAD_LETTER_EXCHANGE);
//设置死信RoutingKey
map.put(“x-dead-letter-routing-key”,“YD”);
//设置过期时间,10秒
map.put(“x-message-ttl”,10000);
return QueueBuilder.durable(QUEUE_A).withArguments(map).build();
}
//声明普通队列 TTL 为40秒
@Bean(“queueB”)
public Queue queueB(){
HashMap<String, Object> map = new HashMap<>(3);
//设置死信交换机
map.put(“x-dead-letter-exchange”,Y_DEAD_LETTER_EXCHANGE);
//设置死信RoutingKey
map.put(“x-dead-letter-routing-key”,“YD”);
//设置过期时间,10秒
map.put(“x-message-ttl”,40000);
return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}
//死信队列
@Bean(“queueD”)
public Queue queueD(){
return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();
}
//绑定
@Bean
public Binding QABindingX(@Qualifier(“queueA”) Queue queueA,
@Qualifier(“xExchange”) DirectExchange xExchange){
return BindingBuilder.bind(queueA).to(xExchange).with(“XA”);
}
@Bean
public Binding QBBindingX(@Qualifier(“queueB”) Queue queueB,
@Qualifier(“xExchange”) DirectExchange xExchange){
return BindingBuilder.bind(queueB).to(xExchange).with(“XB”);
}
@Bean
public Binding QDBindingY(@Qualifier(“queueD”) Queue queueD,
@Qualifier(“yExchange”) DirectExchange yExchange){
return BindingBuilder.bind(queueD).to(yExchange).with(“YD”);
}
}

生产者controller,DeadLetterProducers

//生产者发送延迟消息
@Slf4j
@RestController
public class DeadLetterProducers {
//自动注入
@Autowired
private RabbitTemplate rabbitTemplate;

//发消息
@GetMapping(“/sendMsg/{message}”)
public void sendMsg(@PathVariable String message){
log.info(“当前时间:{},发送一条消息给两个TTL队列:{}”,new Date().toString(),message);
rabbitTemplate.convertAndSend(“X”,“XA”,“消息来自于TTL为10秒的队列:”+message);
rabbitTemplate.convertAndSend(“X”,“XB”,“消息来自于TTL为40秒的队列:”+message);
}
}

消费者:

//消费者
@Slf4j
@Component
public class DeadLetterQueueConsumer {
//接收消息,定义一个监听器来监听死信队列中的消息

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
img

1712532182065)]
[外链图片转存中…(img-3sxiSa7E-1712532182065)]
[外链图片转存中…(img-Wajp1UjT-1712532182066)]
[外链图片转存中…(img-sUNVQtCd-1712532182066)]
[外链图片转存中…(img-wONHwEmK-1712532182066)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
[外链图片转存中…(img-a9fCh6tK-1712532182067)]

  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值