SpringBoot + RabbitMQ从延时队列中删除指定的值【RabbitMQ中的basicAck和basicNack的区别以及basicReject又是什么?】

业务需求是,就是我本来是有一个order-queue队列绑定到了死信队列交换机order-dead-direct-exchange上,然后我的业务是,现在有一个用户下单但是没有付款,order-queue队列写入该条信息并计时24小时后如果用户还是未付款状态则移除到死信队列order-dead-queue中。问题来了,如果在这个24小时内,用户取消订单,这时候就要从order-queue队列中移除该条信息。怎么操作呢?

1、确保依赖的引入


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-amqpartifactId>
dependency>

2、业务代码实现从某个队列中删除指定的值

@Autowired
private RabbitTemplate rabbitTemplate;

@Autowired
private ConnectionFactory connectionFactory;

//取消订单
@PostMapping("/cancelOrder")
public Object cancelOrder(String productId,String dyOrderId,String cancelText,String buyerPaymentState,String orderDeliveryState,String state,String orderId,String buyerPaymentPrice) throws IOException, TimeoutException {

    //删除rabbitMQ中order-queue队列中对应的值? 重新上架商品?
    // 从 order-queue 队列中移除指定订单
    Channel channel = connectionFactory.createConnection().createChannel(false);
    boolean deleted = false;
    while (!deleted) {
        GetResponse response = channel.basicGet("order-queue", false);
        if (response == null) {
            break;
        }
        String messageValue = new String(response.getBody(), StandardCharsets.UTF_8);
        if (messageValue.equals(productId+"_"+dyOrderId)) {
            deleted = true;
            channel.basicAck(response.getEnvelope().getDeliveryTag(), false);
            continue;
        }
        channel.basicNack(response.getEnvelope().getDeliveryTag(), false, true);
    }
    channel.close();
        

这段代码使用 basicGet 方法接收队列中的消息,并使用 basicAck 方法手动确认消费。如果找到包含特定值的消息,就设置 deleted 为 true,并使用 basicAck 确认该消息的消费,然后跳过该消息,最终将其从队列中删除。如果消息的值不等于指定的值,则使用 basicNack 方法将消息放回队列中。这样我们就是实现了从队列中删除指定的值。

需要注意的是,当使用手动确认模式时,如果在消费消息后没有进行确认或拒绝,消息将一直处于 unack 状态,直到消费者关闭或重新连接。这可能会导致消息被重新投递,因此需要确保在处理完每个消息后进行确认或拒绝操作。

3、basicAck 和 basicNack有什么区别呢?

在RabbitMQ中,当消费者从队列中获取到一条消息并进行处理后,需要告诉服务器这条消息已经被成功处理了,这时可以使用basicAck方法来确认消息的消费。而如果处理消息时发生了错误,需要将这条消息重新放回队列中,或者直接将消息丢弃,就可以使用basicNack方法。
basicAck方法表示消费者已经成功地处理了消息,并告诉RabbitMQ可以删除此消息。它的方法签名如下:

void basicAck(long deliveryTag, boolean multiple) throws IOException;

其中,deliveryTag表示消息的唯一标识符,multiple表示是否批量确认(如果设置为true,则表示确认所有小于等于deliveryTag的消息)。

basicNack方法则是表示消费者处理消息时发生了错误,需要将消息重新放回队列中,或者直接将消息丢弃。它的方法签名如下:

void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException;

其中,deliveryTagmultiple的含义与basicAck方法相同,requeue表示是否重新将消息放回队列(如果设置为true,则将消息重新放回队列,如果设置为false,则直接将消息丢弃)。

需要注意的是,basicNack方法并不是所有的AMQP客户端都支持的。如果你的客户端不支持basicNack方法,可以使用basicReject方法来实现相同的效果。

4、basicReject又是什么?

basicReject是AMQP协议提供的一个API,用于拒绝(reject)一条消息,并选择是否将消息重新投递到队列中。它与basicNack类似,但有一些细微的区别。

basicReject的方法签名如下:

void basicReject(long deliveryTag, boolean requeue);

其中,deliveryTag是消息投递标识符,requeue表示是否将消息重新投递到队列中。

basicNack的区别在于,basicReject只能拒绝单个消息,而basicNack可以拒绝多个消息。此外,basicReject无法设置拒绝原因,而basicNack可以设置拒绝原因。

需要注意的是,使用basicRejectbasicNack将会导致RabbitMQ重新将消息投递到队列中,这可能会导致消息的不断重试,因此需要谨慎使用。如果希望立即删除消息而不是重新投递,可以使用basicAck方法。

你可能感兴趣的:(Spring学习笔记,RabbitMQ学习笔记,spring,boot,java-rabbitmq,maven,rabbitmq)