下载延迟插件

Rabbitmq插件下载地址:https://www.rabbitmq.com/community-plugins.html

选择rabbitmq_delayed_message_exchange(一个向RabbitMQ添加延迟消息(或计划消息)的插件)进行下载

现在下载的版本是3.7或者3.8,所以rabbitmq需要3.7以上

下面是rabbitmq_delayed_message_exchange的下载地址:

ez版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.8.0/rabbitmq_delayed_message_exchange-3.8.0.ez

zip版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/archive/v3.8.0.zip

gz版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/archive/v3.8.0.tar.gz

java rabbitmq延迟队列消息无法消费_后端



Rabbitmq安装插件方法

Rabbitmq安装插件的方法:Rabbitmq服务器不附带的所有插件都需要安装。安装方式为将以.ez存档(带有元数据的zip文件)的插件文件。复制或者放到RABBITMQ_PLUGINS_DIR 文件夹下,RABBITMQ_PLUGINS_DIR即rabbitmq安装目录下的plugins目录。通过rabbitmq-plugins enable命令来启动插件,可以通过rabbitmq-plugins list命令来查看Rabbitmq已经安装的插件。



安装延迟插件

先移动到rabbitmq的安装目录下的plugins目录,使用上面的下载地址来下载插件。(我直接下载的是ez版本,plugins下的插件需要的就是ez版本,所以不用解压操作什么的)

wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.8.0/rabbitmq_delayed_message_exchange-3.8.0.ez

java rabbitmq延迟队列消息无法消费_github_02

下载完成之后,进入sbin目录启用插件:

./rabbitmq-plugins enable rabbitmq_delayed_message_exchange

然后检查安装的插件,看是否安装成功(看是否有rabbitmq_delayed_message相关的插件)

./rabbitmq-plugins list

java rabbitmq延迟队列消息无法消费_linux_03

还可以直接在rabbitmq的管理页面的添加交换机的Type属性上看是否多了个x-delayed-message,如果有,说明安装成功

java rabbitmq延迟队列消息无法消费_java_04

windows下的安装方法也是一样的,只是以下两条命令有所不同而已

进入sbin目录启用插件:

#windows

./rabbitmq-plugins.bat enable rabbitmq_delayed_message_exchange

查看安装的插件
#windows

./rabbitmq-plugins.bat list



使用插件实现延迟队列

安装完成之后,我们就可以使用延迟队列了

插件方式实现延迟队列的流程如下:

1、生产者将一个设置有延迟时间的消息(msg)和路由键(routekey)发送指定的延时交换机(exchange)上

2、延时交换机(exchange)存储消息等待消息到期根据路由键(routekey)找到绑定自己的队列(queue)并把消息给它

3、队列(queue)再把消息发送给监听它的消费者(customer)

相对于TTL实现延迟队列,插件方式实现较简单,也无需定义那么多的rabbitmq组件。

实例

1、进行延时交换机和延迟队列的注册

//下面是一个延迟队列的注册类

@Configuration
public class RabbitmaqConfig {

    /**
     * 延时交换机,交换机类型为CustomExchange
     */
    @Bean
    public CustomExchange customExchange(){
        Map<String,Object>args=new HashMap<>();
        //延时交换机一定要设置x-delayed-type属性
        args.put("x-delayed-type", "direct");
        //第二个参数type需要设置成x-delayed-message
        return new CustomExchange("delay_exchange","x-delayed-message",true,false,args);

    }


    /**
     * 延时队列
     * @return
     */
    @Bean
    public Queue delayQueue(){
        return new Queue("delay_queue",true);
    }

    /**
     * 延时队列绑定交换机
     * @return
     */
    @Bean
    public Binding delayBinding(){
        return BindingBuilder.bind(delayQueue()).to(customExchange()).with("delay_key").noargs();
    }


}

说明:插件的延迟消息主要是通过延迟交换机来实现的,所以我们在注册延迟交换机时必须添加上x-delayed-type属性,并且声明消息类型为x-delayed-message,而不是普通的交换机。

2、延时消息发送类

@Component
@Slf4j
public class RabbitmqSend {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送延时消息
     * @param msg
     */
    public void sendDelayMessage(Object msg,Long delayTime){
        rabbitTemplate.convertAndSend( "delay_exchange", "delay_key",msg,
                message -> {
                    //设置延迟时间
                    message.getMessageProperties().setHeader("x-delay",delayTime);
                    return message;
                });
        log.info("发送延迟消息:{},延时:{}毫秒",msg,delayTime);
    }
}

说明:插件类的延时消息,只需要在header上设置x-delay值即可,单位为毫秒

消费类跟普通的消息消费类一样

简单写一个消费类

@Component
@Slf4j
public class RabbitmqRecover {

    @RabbitListener(queues = "delay_queue")
    public void recover(String msg,Message message, Channel channel){
        log.info("接收时间:{},接受内容:{}", LocalDateTime.now(), msg);
        //通知 MQ 消息已被接收,可以ACK(从队列中删除)了
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }catch (Exception e){
            log.error("消息消费失败!错误信息:{}",e.getMessage());
        }

    }
}

测试一下

@RestController
public class RabbitmqController {

    @Autowired
    private RabbitmqProduce produce;

    @Autowired
    private RabbitmqSend sender;

    @GetMapping("/rabbitmq")
    public void send() throws Exception {
        sender.sendDelayMessage("这是一个延迟消息",6000L);
    }
}

调用接口,输出以下结果,可以看到,发送和消费刚好相差6秒,实现延迟队列成功!

2020-07-06 15:58:08.431  INFO 40620 --- [nio-8080-exec-1] com.example.demo.rabbitmq.RabbitmqSend   : 发送延迟消息:这是一个延迟消息,延时:6000毫秒
2020-07-06 15:58:14.477  INFO 40620 --- [ntContainer#1-2] c.example.demo.rabbitmq.RabbitmqRecover  : 接收时间:2020-07-06T15:58:14.477868600,接受内容:这是一个延迟消息,headers:{__TypeId__=java.lang.String}