springboot+RabbitMQ做延迟消息详解(二)--插件延时,已运用到公司项目中

此方法已用到公司商城项目,可用。

业务:双十一商品按指定时间上架;
拼团活动按指定时间上下架;
预售活动按指定时间上下架;
优惠卷活动按指定时间上下架;

思路: 1.定时任务 --可行,但不合适
缺点:因为活动会有很多很多,不知道这些活动的具体的上架时间,也就是说,定时任务只能设置每秒执行一次,服务器的压力大。
2.死信来做延时 --不可行。
死信原理:将消息投放到某队列中(表面队列),改队列无消费者,消息时间到了无法消费,变为死消息,进入死信队列,进行正真的消费,来做到消息的延时。
原因:比如我双十一有两个拼团活动,我先设置拼团A在11.11日0点上架,然后设置拼团B在11.10日晚上10点就开始上架,这里因为A的消息先进入队列,B消息后进入队列,A消息在消费前会阻塞B消息消费的,所以11.10日晚上10点B消息延时的时间到了,B消息消费不了,消息消费被阻塞了,要等A消息消费了,B消息才能消费。
3.rabbitmq的插件做动态延时 --可行
原理:将需要延时的消息投放到延迟交换机里,时间到了,才会通过路由转发到队列里直接消费,避免了消息在队列做延迟可能发生的阻塞情况。

插件下载链接:https://www.rabbitmq.com/community-plugins.html
选择这个 :rabbitmq延迟交换的这个在这里插入图片描述
配置插件:
1.windows
下载后把插件放到 plugins 里面,然后到 sbin里面打开cmd,执行 rabbitmq-plugins enable rabbitmq_delayed_message_exchange 命令,然后重启mq即可
2.linux
下载好后解压到plugins里面,执行命令 rabbitmq-plugins enable rabbitmq_delayed_message_exchange,然后重启mq即可

pmx配置


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

boot项目配置mq


spring:
  rabbitmq:
      host: ***
      port: 5672
      username: ***
      password: ***
      #设置手动ack回执
      listener:
        simple:
          acknowledge-mode: manual
          #none 不确认,auto 自动确认 manual 手动确认

配置rabbitmq的队列、交换机及其转发路由


  //商品按指定上架时间相关的常量
    private final static String EXCHANGE_NAME = "pms_publish_exchange";
    private final static String QUEUE_NAME = "pms_publish_queue";
    private final static String ROUTE_KEY = "pms_publish_routekey";

    /**
     * 绑定的交换机,使用rabbitmq_delayed_message_exchange
     */
    @Bean("prductExchange")
    public CustomExchange productExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(EXCHANGE_NAME,"x-delayed-message",true, false,args);
    }
    /**
     * 消费队列
     */
    @Bean("productQueue")
    public Queue productQueue() {
        return new Queue(QUEUE_NAME);
    }
    /**
     * 延迟队列绑定到交换机
     */
    @Bean
    public Binding productBinding(@Qualifier("productQueue") Queue assembleQueue, @Qualifier("prductExchange") CustomExchange cfgUserDelayExchange){
        return BindingBuilder.bind(assembleQueue).to(cfgUserDelayExchange).with(ROUTE_KEY).noargs();
    }

生产者:


@Component
public class RabbitMQPublishSender {
    //商品上架
    private final static String EXCHANGE_NAME = "pms_publish_exchange";
    private final static String QUEUE_NAME = "pms_publish_queue";
    private final static String ROUTE_KEY = "pms_publish_routekey";

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void productPublish(Long productId, Long expirationTime) {
        this.amqpTemplate.convertAndSend(EXCHANGE_NAME, ROUTE_KEY, productId, message -> {
            // 如果配置了 params.put("x-message-ttl", 5 * 1000); 那么这一句也可以省略,具体根据业务需要是声明 Queue 的时候就指定好延迟时间还是在发送自己控制时间
            message.getMessageProperties().setHeader("x-delay",expirationTime);
            return message;
        });
    }
 }

消费者:


@Component
public class RabbitMQPublishReceiver {

    @Autowired
    private PmsProductService pmsProductService;

    @RabbitListener(queues = "pms_publish_queue")
    @RabbitHandler
    public void productDelayQueue(Long productId, Message message, Channel channel) throws IOException {
        //ack回执
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        //商品上架
        pmsProductService.publish(productId);
    }
}    

按指定时间上架业务:
这里业务处理的部分各不相同直接上图好了,主旨就是把延时的时间算出来放入生产者即可。

上架的业务:
就是简单的改个上架字段的状态,直接上图。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值