java rabbitmq 应用场景_springboot rabbitmq 死信队列应用场景

何为死信队列?

死信队列实际上就是,当我们的业务队列处理失败(比如抛异常并且达到了retry的上限),就会将消息重新投递到另一个Exchange(Dead Letter Exchanges),该Exchange再根据routingKey重定向到另一个队列,在这个队列重新处理该消息。

来自一个队列的消息可以被当做‘死信’,即被重新发布到另外一个“exchange”去,这样的情况有:

消息被拒绝 (basic.reject or basic.nack) 且带 requeue=false 参数

消息的TTL-存活时间已经过期

队列长度限制被超越(队列满)

Dead letter exchanges (DLXs) are normal exchanges.

For any given queue, a DLX can be defined by clients using the queue's arguments, or in the server using policies.

配置文件

设置重试次数、间隔和投递到死信队列

spring.application.name=spring-boot-rabbitmq

spring.rabbitmq.host=localhost

spring.rabbitmq.port=5672spring.rabbitmq.username=nut

spring.rabbitmq.password=nut

# 允许消息消费失败的重试

spring.rabbitmq.listener.simple.retry.enabled=true# 消息最多消费次数3次

spring.rabbitmq.listener.simple.retry.max-attempts=3# 消息多次消费的间隔1秒

spring.rabbitmq.listener.simple.retry.initial-interval=1000# 设置为false,会丢弃消息或者重新发布到死信队列

spring.rabbitmq.listener.simple.default-requeue-rejected=falseserver.port=5678

初始化和绑定重定向队列配置类

import org.springframework.amqp.core.*;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.HashMap;importjava.util.Map;/*** 死信队列的配置*/@Configurationpublic classRabbitDeadLetterConfig {public static final String DEAD_LETTER_EXCHANGE = "TDL_EXCHANGE";public static final String DEAD_LETTER_TEST_ROUTING_KEY = "TDL_KEY";public static final String DEAD_LETTER_REDIRECT_ROUTING_KEY = "TKEY_R";public static final String DEAD_LETTER_QUEUE = "TDL_QUEUE";public static final String REDIRECT_QUEUE = "TREDIRECT_QUEUE";/*** 死信队列跟交换机类型没有关系 不一定为directExchange 不影响该类型交换机的特性.*/@Bean("deadLetterExchange")publicExchange deadLetterExchange() {return ExchangeBuilder.directExchange(DEAD_LETTER_EXCHANGE).durable(true).build();

}

@Bean("deadLetterQueue")publicQueue deadLetterQueue() {

Map args = new HashMap<>(2);//x-dead-letter-exchange 声明 死信队列Exchange

args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);//x-dead-letter-routing-key 声明 死信队列抛出异常重定向队列的routingKey(TKEY_R)

args.put("x-dead-letter-routing-key", DEAD_LETTER_REDIRECT_ROUTING_KEY);returnQueueBuilder.durable(DEAD_LETTER_QUEUE).withArguments(args).build();

}

@Bean("redirectQueue")publicQueue redirectQueue() {returnQueueBuilder.durable(REDIRECT_QUEUE).build();

}/*** 死信队列绑定到死信交换器上.

*

*@returnthe binding*/@BeanpublicBinding deadLetterBinding() {return new Binding(DEAD_LETTER_QUEUE, Binding.DestinationType.QUEUE, DEAD_LETTER_EXCHANGE, DEAD_LETTER_TEST_ROUTING_KEY, null);

}/*** 将重定向队列通过routingKey(TKEY_R)绑定到死信队列的Exchange上

*

*@returnthe binding*/@BeanpublicBinding redirectBinding() {return new Binding(REDIRECT_QUEUE, Binding.DestinationType.QUEUE, DEAD_LETTER_EXCHANGE, DEAD_LETTER_REDIRECT_ROUTING_KEY, null);

}

}

生产者向业务队列发送消息

这里为了方便测试没有往业务队列发送消息,直接往死信Exchange里投递消息。

importlombok.extern.slf4j.Slf4j;importorg.springframework.amqp.rabbit.core.RabbitTemplate;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importxy.study.rabbitmq.conf.RabbitDeadLetterConfig;

@Slf4j

@Componentpublic classDeadLetterSender {

@AutowiredprivateRabbitTemplate rabbitTemplate;public void send(intnumber) {

log.warn("DeadLetterSender : {}", number);//这里的Exchange可以是业务的Exchange,为了方便测试这里直接往死信Exchange里投递消息

rabbitTemplate.convertAndSend(

RabbitDeadLetterConfig.DEAD_LETTER_EXCHANGE,

RabbitDeadLetterConfig.DEAD_LETTER_TEST_ROUTING_KEY,

number);

}

}

死信队列消费者

这里会抛异常

importlombok.extern.slf4j.Slf4j;importorg.springframework.amqp.rabbit.annotation.RabbitHandler;importorg.springframework.amqp.rabbit.annotation.RabbitListener;importorg.springframework.messaging.handler.annotation.Payload;importorg.springframework.stereotype.Component;importxy.study.rabbitmq.conf.RabbitDeadLetterConfig;

@Slf4j

@Component

@RabbitListener(queues=RabbitDeadLetterConfig.DEAD_LETTER_QUEUE)public classDeadLetterConsumer {/*@RabbitListener(bindings = @QueueBinding(

value = @Queue(value = RabbitDeadLetterConfig.DEAD_LETTER_QUEUE, durable = "true"),

exchange = @Exchange(value = RabbitDeadLetterConfig.DEAD_LETTER_EXCHANGE, type = ExchangeTypes.DIRECT),

key = RabbitDeadLetterConfig.DEAD_LETTER_TEST_ROUTING_KEY)

)*/@RabbitHandlerpublic voidtestDeadLetterQueueAndThrowsException(@Payload Integer number){

log.warn("DeadLetterConsumer :{}/0 ", number);int i = number / 0;

}

}

重定向队列

队列"死信"后,会将消息投递到Dead Letter Exchanges,然后该Exchange会将消息投递到重定向队列。

此时,在重定向队列中,做对应的业务操作。

importlombok.extern.slf4j.Slf4j;importorg.springframework.amqp.rabbit.annotation.RabbitHandler;importorg.springframework.amqp.rabbit.annotation.RabbitListener;importorg.springframework.stereotype.Component;importxy.study.rabbitmq.conf.RabbitDeadLetterConfig;

@RabbitListener(queues=RabbitDeadLetterConfig.REDIRECT_QUEUE)

@Component

@Slf4jpublic classRedirectQueueConsumer {/*** 重定向队列和死信队列形参一致Integer number

*@paramnumber*/@RabbitHandlerpublic voidfromDeadLetter(Integer number){

log.warn("RedirectQueueConsumer : {}", number);//对应的操作

int i = number / 1;

}

}

测试

先启动项目

然后利用测视类发送一条信息

importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importxxx.DeadLetterSender;

@RunWith(SpringRunner.class)

@SpringBootTestpublic classRabbitmqApplicationTests {

@AutowiredprivateDeadLetterSender deadLetterSender;

@Testpublic voidtestSendDeadLetterQueue(){

deadLetterSender.send(15);

}

}

再看RabbitmqApplication控制台日志

重试3次后,消息不再入队,投递到DL Exchange,路由到重定向队列。

参考:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值