基于RabbitMQ延迟插件实现超时订单的自动取消

在使用RabbitMQ实现超时订单自动取消时,有两种解决方案,死信队列和延迟插件。

死信队列主要依赖的是死信队列和延迟队列的特新。通过设置消息存活时间,并且在指定时间内未能被消费,从而进入死信队列。消费者通过监听死信队列来处理订单的自动取消。这种方案的缺点就是可能存在消息阻塞的问题,影响后面消息消费。还有就是方案复杂,需要声明多个队列出来,增加系统的复杂度。

延迟插件使用就比较简单。基于rabbitmq_delayed_message_exchange插件,创建x-delayed-message类型的消息队列,当有延迟消息时,先会把消息存放在一个基于Erlang开发的Mnesia数据库中,然后通过定时器查询消息,并将消息投送到 x-delayed-message消息队列中。消费者监听x-delayed-message完成订单处理。

下面是基于延迟插件的实例

1. 生产端的实现

这里使用的是RabbitMQ Java客户端库com.rabbitmq:amqp-client

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class DelayedMessagePublisher {

    private static final String EXCHANGE_NAME = "delayed_orders";
    private static final String ROUTING_KEY = "order.timeout";

    public void publishDelayedMessage(String message, int delayInSeconds) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // 设置RabbitMQ服务器地址
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {

            // 声明一个延迟交换机,并设置类型为"x-delayed-message"
            channel.exchangeDeclare(EXCHANGE_NAME, "x-delayed-message", true, false, null);

            // 准备消息属性,设置延迟时间戳(单位为毫秒)
            AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                    .headers(new HashMap<String, Object>() {{
                        put("x-delay", delayInSeconds * 1000L); // 将延迟时间转换为毫秒
                    }})
                    .build();

            // 发布带有延迟的消息
            channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, properties, message.getBytes());

            System.out.println("Sent order cancellation message with delay of " + delayInSeconds + " seconds.");
        }
    }

    public static void main(String[] args) throws IOException, TimeoutException {
        DelayedMessagePublisher publisher = new DelayedMessagePublisher();
        publisher.publishDelayedMessage("Order timeout for orderId XYZ", 60); // 发送一条将在60秒后投递的消息
    }
}

在上述代码中,声明了一个延迟交换机,并设置了消息头x-delay来指定消息的延迟投递时间。消费端可以像普通队列那样绑定到这个延迟交换机,并定义自己的路由键规则。

2. 消费者的实现

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class DelayedMessageConsumer {

    private static final String QUEUE_NAME = "order_timeout_queue";
    private static final String EXCHANGE_NAME = "delayed_orders";
    private static final String ROUTING_KEY = "order.timeout";

    public void consumeDelayedMessages() throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // 设置RabbitMQ服务器地址
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {

            // 声明队列并绑定到延迟交换机
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);

            // 定义消费者并启动消费循环
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println("Received delayed message: " + message);
                
                // 在此处添加处理订单超时取消的逻辑
                handleOrderCancellation(message);
            };
            CancelCallback cancelCallback = consumerTag -> System.out.println("Consumer cancelled");

            channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
        }
    }

    private void handleOrderCancellation(String message) {
        // 根据接收到的消息内容(例如订单ID),调用相应的服务接口或方法进行订单取消操作
        // 示例代码如下:
        System.out.println("Cancelling order due to timeout: " + message);
        // ... 实际操作,如更新数据库中的订单状态、释放库存、发送通知等
    }

    public static void main(String[] args) throws IOException, TimeoutException {
        DelayedMessageConsumer consumer = new DelayedMessageConsumer();
        consumer.consumeDelayedMessages();
    }
}

在上述代码中,首先声明并绑定了一个队列到延迟交换机,当带有延迟的消息到达时,会自动投递到此队列。然后,创建了一个消费者,当有新消息投递到队列时,回调函数deliverCallback会被调用,从而执行订单超时取消的逻辑。实际应用中,handleOrderCancellation方法内应包含调用相关服务接口或方法来执行订单取消的具体操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值