RabbitMQ操作

RabbitMQ的消息模

在这里插入图片描述
在这里插入图片描述

业务场景说明

用于解决用户下单以后,订单超时如何取消订单的问题。

用户进行下单操作(会有锁定商品库存、使用优惠券、积分一系列的操作);

生成订单,获取订单的id;

获取到设置的订单超时时间(假设设置的为60分钟不支付取消订单);

按订单超时时间发送一个延迟消息给RabbitMQ,让它在订单超时后触发取消订单的操作;

如果用户没有支付,进行取消订单操作(释放锁定商品库存、返还优惠券、返回积分一系列操作)。

整合RabbitMQ实现延迟消息

在pom.xml中添加相关依赖

 <dependency> 
  <groupId>org.springframework.boot</groupId>   
  <artifactId>spring-boot-starter-amqp</artifactId>
  </dependency>
  

修改SpringBoot配置文件
修改application.yml文件,在spring节点下添加RabbitMQ相关配置。

rabbitmq:
host: localhost
port: 5672
virtual-host: /mall
username: mall
password: mall
publisher-confirms: true #如果对异步消息需要回调必须设置为true

在这里插入图片描述
添加消息队列的枚举配置类QueueEnum

用于延迟消息队列及处理取消订单消息队列的常量定义,包括交换机名称、队列名称、路由键名称。

/**

  • 消息队列枚举配置

  • Created by macro on 2018/9/14.
    /
    @Getter
    public enum QueueEnum {
    /
    *

    • 消息通知队列
      /
      QUEUE_ORDER_CANCEL(“mall.order.direct”, “mall.order.cancel”, “mall.order.cancel”),
      /
      *
    • 消息通知ttl队列
      */
      QUEUE_TTL_ORDER_CANCEL(“mall.order.direct.ttl”, “mall.order.cancel.ttl”, “mall.order.cancel.ttl”);

    /**

    • 交换名称
      /
      private String exchange;
      /
      *
    • 队列名称
      /
      private String name;
      /
      *
    • 路由键
      */
      private String routeKey;

    QueueEnum(String exchange, String name, String routeKey) {
    this.exchange = exchange;
    this.name = name;
    this.routeKey = routeKey;
    }

添加RabbitMQ的配置

用于配置交换机、队列及队列与交换机的绑定关系。
/**

  • 消息队列配置

  • Created by macro on 2018/9/14.
    */
    @Configuration
    public class RabbitMqConfig {

    /**

    • 订单消息实际消费队列所绑定的交换机
      */
      @Bean
      DirectExchange orderDirect() {
      return (DirectExchange) ExchangeBuilder
      .directExchange(QueueEnum.QUEUE_ORDER_CANCEL.getExchange())
      .durable(true)
      .build();
      }

    /**

    • 订单延迟队列队列所绑定的交换机
      */
      @Bean
      DirectExchange orderTtlDirect() {
      return (DirectExchange) ExchangeBuilder
      .directExchange(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange())
      .durable(true)
      .build();
      }

    /**

    • 订单实际消费队列
      */
      @Bean
      public Queue orderQueue() {
      return new Queue(QueueEnum.QUEUE_ORDER_CANCEL.getName());
      }

    /**

    • 订单延迟队列(死信队列)
      */
      @Bean
      public Queue orderTtlQueue() {
      return QueueBuilder
      .durable(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getName())
      .withArgument(“x-dead-letter-exchange”, QueueEnum.QUEUE_ORDER_CANCEL.getExchange())//到期后转发的交换机
      .withArgument(“x-dead-letter-routing-key”, QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey())//到期后转发的路由键
      .build();
      }

    /**

    • 将订单队列绑定到交换机
      */
      @Bean
      Binding orderBinding(DirectExchange orderDirect,Queue orderQueue){
      return BindingBuilder
      .bind(orderQueue)
      .to(orderDirect)
      .with(QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey());
      }

    /**

    • 将订单延迟队列绑定到交换机
      */
      @Bean
      Binding orderTtlBinding(DirectExchange orderTtlDirect,Queue orderTtlQueue){
      return BindingBuilder
      .bind(orderTtlQueue)
      .to(orderTtlDirect)
      .with(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey());
      }

}

在RabbitMQ管理页面可以看到以下交换机和队列

在这里插入图片描述

交换机及队列说明

mall.order.direct(取消订单消息队列所绑定的交换机):绑定的队列为mall.order.cancel,一旦有消息以mall.order.cancel为路由键发过来,会发送到此队列。
mall.order.direct.ttl(订单延迟消息队列所绑定的交换机):绑定的队列为mall.order.cancel.ttl,一旦有消息以mall.order.cancel.ttl为路由键发送过来,会转发到此队列,并在此队列保存一定时间,等到超时后会自动将消息发送到mall.order.cancel(取消订单消息消费队列)。

添加延迟消息的发送者CancelOrderSender

用于向订单延迟消息队列(mall.order.cancel.ttl)里发送消息。
/**

  • 取消订单消息的发出者

  • Created by macro on 2018/9/14.
    */
    @Component
    public class CancelOrderSender {
    private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderSender.class);
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMessage(Long orderId,final long delayTimes){
    //给延迟队列发送消息
    amqpTemplate.convertAndSend(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange(), QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey(), orderId, new MessagePostProcessor() {
    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
    //给消息设置延迟毫秒值
    message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
    return message;
    }
    });
    LOGGER.info(“send orderId:{}”,orderId);
    }
    }

添加取消订单消息的接收者CancelOrderReceiver

用于从取消订单的消息队列(mall.order.cancel)里接收消息。

/**

  • 取消订单消息的处理者
  • Created by macro on 2018/9/14.
    */
    @Component
    @RabbitListener(queues = “mall.order.cancel”)
    public class CancelOrderReceiver {
    private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderReceiver.class);
    @Autowired
    private OmsPortalOrderService portalOrderService;
    @RabbitHandler
    public void handle(Long orderId){
    portalOrderService.cancelOrder(orderId);
    LOGGER.info(“process orderId:{}”,orderId);
    }
    }

添加OmsPortalOrderService接口

**

  • 前台订单管理Service

  • Created by macro on 2018/8/30.
    */
    public interface OmsPortalOrderService {

    /**

    • 根据提交信息生成订单
      */
      @Transactional
      CommonResult generateOrder(OrderParam orderParam);

    /**

    • 取消单个超时订单
      */
      @Transactional
      void cancelOrder(Long orderId);

}

添加OmsPortalOrderService的实现类OmsPortalOrderServiceImpl

在这里插入图片描述

添加OmsPortalOrderController定义接口

在这里插入图片描述

进行接口测试

调用下单接口

注意:已经将延迟消息时间设置为30秒
在这里插入图片描述

项目源码地址
https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-08
原文地址:
https://mp.weixin.qq.com/s?__biz=MzU1Nzg4NjgyMw==&mid=2247483734&idx=1&sn=fa9af8e9f72e7443126aed0f7a64b88b&scene=21#wechat_redirect

### RabbitMQ 的使用教程及相关常见操作 #### 1. RabbitMQ 基本概念概述 RabbitMQ 是一种基于 AMQP(高级消息队列协议)的消息中间件,用于在分布式系统之间传递消息。以下是几个核心概念: - **Publisher**: 发布者负责向交换器发送消息[^1]。 - **Exchange**: 负责接收来自发布者的消息并将其路由到绑定的队列中[^2]。 - **Queue**: 存储消息的地方,直到消费者处理它们为止。 - **Consumer**: 订阅特定队列中的消息,并对其进行处理。 这些组件共同构成了 RabbitMQ 的工作流程。 --- #### 2. 安装与启动 RabbitMQ 安装 RabbitMQ 需要先安装 Erlang 运行环境,因为 RabbitMQ 是用 Erlang 编写的。以下是一个简单的安装过程(以 Linux 系统为例): ```bash # 更新包管理器索引 sudo apt update # 安装 Erlang sudo apt install erlang # 添加 RabbitMQ 官方源 sudo wget https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc sudo apt-key add rabbitmq-release-signing-key.asc # 安装 RabbitMQ sudo apt install rabbitmq-server # 启动服务 sudo systemctl start rabbitmq-server # 查看状态 sudo systemctl status rabbitmq-server ``` 完成上述步骤后,可以通过 `http://localhost:15672` 登录 Web 控制台,默认用户名和密码为 `guest/guest`。 --- #### 3. RabbitMQ 常见操作 ##### (1) 创建 Exchange 和 Queue 并绑定 创建一个 Direct 类型的 Exchange,并将它与一个 Queue 绑定: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() # 声明 exchange channel.exchange_declare(exchange='direct_logs', exchange_type='direct') # 声明 queue result = channel.queue_declare(queue='', exclusive=True) queue_name = result.method.queue # 将 queue 绑定到 exchange 上 severities = ['info', 'error'] for severity in severities: channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key=severity) print(f' [*] Waiting for logs. To exit press CTRL+C') ``` 此代码片段展示了如何声明 Exchange 和 Queue,并通过指定的 Routing Key 实现绑定关系。 --- ##### (2) 发送消息至 Exchange 下面是如何通过 Python 向 Exchange 发送一条消息的例子: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() message = 'Hello World!' routing_key = 'info' channel.basic_publish( exchange='direct_logs', routing_key=routing_key, body=message ) print(f" [x] Sent {routing_key}:{message}") connection.close() ``` 这段代码会将消息发送给名为 `direct_logs` 的 Exchange,并由该 Exchange 根据 Routing Key 来决定目标 Queue--- ##### (3) 接收消息 消费者可以从某个 Queue 中获取消息: ```python def callback(ch, method, properties, body): print(f" [x] Received {body}") channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True) print(' [*] Waiting for messages. To exit press CTRL+C') channel.start_consuming() ``` 当有新消息到达时,回调函数会被触发来处理接收到的数据。 --- #### 4. 常见配置优化建议 为了提高性能或满足特殊需求,可以考虑调整以下几个参数: - 设置持久化选项 (`durable`),使消息即使在服务器重启后仍然存在。 - 使用确认机制 (`acknowledgment`),确保每条消息都被成功消费后再删除。 - 如果需要支持高并发场景,则应合理规划 Prefetch Count 参数,控制单个 Consumer 处理的最大未确认消息数。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值