@Bean
public Queue yewu1DemoRetryQueue() {
Map<String, Object> args = new ConcurrentHashMap<>(3);
// 将消息重新投递到业务交换机Exchange中
args.put(RETRY_LETTER_QUEUE_KEY, BusinessConfig.YEWU1_EXCHANGE);
args.put(RETRY_LETTER_ROUTING_KEY, BusinessConfig.YEWU1_DEMO_ROUTINGKEY);
// 消息在队列中延迟3s后超时,消息会重新投递到x-dead-letter-exchage对应的队列中,routingkey为自己指定
args.put(RETRY_MESSAGE_TTL, 3 * 1000);
return new Queue(YEWU1_DEMO_RETRY_QUEUE_NAME, true, false, false, args);
}
/**
-
绑定以上定义关系
-
@return
*/
@Bean
public Binding retryDirectBinding() {
return BindingBuilder.bind(yewu1DemoRetryQueue()).to(yewu1RetryExchange())
.with(YEWU1_DEMO_RETRY_ROUTING_KEY);
}
}
3.死信队列
声明私信队列与绑定关系。
@Configuration
public class DeadConfig {
/**
- 死信队列
*/
public final static String FAIL_QUEUE_NAME = “fail_queue”;
/**
- 死信交换机
*/
public final static String FAIL_EXCHANGE_NAME = “fail_exchange”;
/**
- 死信routing
*/
public final static String FAIL_ROUTING_KEY = “fail_routing”;
/**
-
创建配置死信队列
*/
@Bean
public Queue deadQueue() {
return new Queue(FAIL_QUEUE_NAME, true, false, false);
}
/**
-
死信交换机
-
@return
*/
@Bean
public DirectExchange deadExchange() {
DirectExchange directExchange = new DirectExchange(FAIL_EXCHANGE_NAME, true, false);
return directExchange;
}
/**
-
绑定关系
-
@return
*/
@Bean
public Binding failBinding() {
return BindingBuilder.bind(deadQueue()).to(deadExchange()).with(FAIL_ROUTING_KEY);
}
}
4.生产者
生产者如上文,通用代码。
@RestController
@RequestMapping(“/TestRabbit”)
public class ProducerDemo {
@Resource
private RabbitTemplate rabbitTemplate;
//@RequestMapping(“/sendDirect”)
String sendDirect(@RequestBody String message) throws Exception {
System.out.println(“开始生产”);
CorrelationData data = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(BusinessConfig.YEWU1_EXCHANGE, BusinessConfig.YEWU1_DEMO_ROUTINGKEY,
message, data);
System.out.println(“结束生产”);
System.out.println(“发送id:” + data);
return “OK,sendDirect:” + message;
}
}
5.消费者
大量的逻辑,请参考注释。
public enum RabbitEnum {
/**
- 处理成功
*/
ACCEPT,
/**
- 可以重试的错误
*/
RETRY,
/**
- 无需重试的错误
*/
REJECT
@Component
public class ConsumerDemo {
private final static Logger logger = LoggerFactory.getLogger(ConsumerDemo.class);
@Resource
private RabbitTemplate rabbitTemplate;
// @RabbitListener(queues = “yewu1_demo_queue”)
protected void consumer(Message message, Channel channel) throws Exception {
RabbitEnum ackSign = RabbitEnum.RETRY;
System.out.println(message.getMessageProperties().getCorrelationId());
try {
// 可以加入重复消费判断
int i = 1 / 0;
} catch (Exception e) {
ackSign = RabbitEnum.RETRY;
throw e;
} finally {
// 通过finally块来保证Ack/Nack会且只会执行一次
if (ackSign == RabbitEnum.ACCEPT) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} else if (ackSign == RabbitEnum.RETRY) {
String correlationData =
(String)message.getMessageProperties().getHeaders().get(“spring_returned_message_correlation”);
System.out.println(message.getMessageProperties().getCorrelationId());
long retryCount = getRetryCount(message.getMessageProperties());
if (retryCount >= 3) {
// 重试次数超过3次,则将消息发送到失败队列等待特定消费者处理或者人工处理
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
rabbitTemplate.convertAndSend(DeadConfig.FAIL_EXCHANGE_NAME, DeadConfig.FAIL_ROUTING_KEY,
message, new CorrelationData(correlationData));
logger.info(“连续失败三次,将消息发送到死信队列,发送消息:” + new String(message.getBody()));
} catch (Exception e1) {
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
logger.error(“发送死信队列报错:” + e1.getMessage() + “,原始消息:” + new String(message.getBody()));
}
} else {
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-WSQOdNvt-1710838024150)]
[外链图片转存中…(img-UbBomROc-1710838024151)]
[外链图片转存中…(img-mjp6Psfi-1710838024151)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-cGL6evyF-1710838024152)]