RabbitMQ插件实现延迟队列

安装 rabbitmq:

 brew install rabbitmq

 

创建远程访问用户:

进入rabbitmq 目录下的 plugins 目录执行添加用户,添加用户权限,设置用户角色操作

      添加用户
            ./rabbitmqctl add_user admin admin


      添加用户权限
            ./rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"


      设置用户角色

            ./rabbitmqctl set_user_tags admin administrator

         

1 安装erlang

brew install erlang 

2 安装插件

  • 第一步: 下载插件

    下载地址:http://www.rabbitmq.com/community-plugins.html

  • 第二步:把下载好的插件解压到rabbitmq 目录下的 plugins 目录

    /usr/local/Cellar/rabbitmq/3.7.3/plugins 
  • 第三步:启动插件

    rabbitmq-plugins enable rabbitmq_delayed_message_exchange

 

3 rabbitmq 页面新建Exchange时看到 type 多出一项 x-delayed-message 表示安装成功

 

 

 

 

 

 

rabbitmq插件实现延时队列代码:

application.yml:

rabbitmq:
  host: 192.168.1.237
  port: 5672
  username: admin
  password: admin
  publisher-confirms: true    #消息发送到交换机确认机制,是否确认回调
  publisher-returns: true     #消息失败返回,比如路由不到队列时触发回调
  listener:
    simple:
      acknowledge-mode: manual #设置消费着的手动确认 ack

 

RabbitConfig:

@Configuration
public class RabbitConfig {

    private static final Logger log = LoggerFactory.getLogger(RabbitConfig.class);


    @Resource
    private RabbitTemplate rabbitTemplate;



    @Bean
    public AmqpTemplate amqpTemplate() {
        Logger log = LoggerFactory.getLogger(RabbitTemplate.class);
        // 消息发送失败返回到队列中,yml需要配置 publisher-returns: true
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            log.info("ReturnCallback回调消息:{} 发送失败, 应答码:{} 原因:{} 交换机: {}  路由键: {}", message, replyCode, replyText, exchange, routingKey);
        });
        // 消息确认,yml需要配置 publisher-confirms: true
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息发送到exchange成功,id: {}", correlationData);
            } else {
                log.info("消息发送到exchange失败,原因: {}", cause);
            }
        });
        return rabbitTemplate;
    }

    /**
     * 自定义的交换机类型
     * @return
     */
    @Bean
    CustomExchange delayedExchange() {
        Map<String,Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange("delayedExchange","x-delayed-message",true,false,args);
    }

    /**
     * 创建一个队列
     * @return
     */
    @Bean
    public Queue delayedQueue() {
        return new Queue("delayedQueue",true);
    }

    /**
     * 绑定队列到自定义交换机
     * @return
     */
    @Bean
    public Binding bindingNotify() {
        return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with("delayedQueue").noargs();
    }
}

 

生产者:

@Component
public class DelayedSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send(String msg, long time) {
        System.out.println("DelayedSender 发送时间: " + LocalDateTime.now() + " msg内容:" + msg);
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setHeader("x-delay", time);
                return message;
            }
        };
        this.rabbitTemplate.convertAndSend("delayedExchange", "delayedQueue", msg, messagePostProcessor);
    }

}

 

消费者:

@Component
public class DelayedReceiver {

    @RabbitListener(queues = "delayedQueue")
    @RabbitHandler
    public void process(String msg, Message message, Channel channel) throws IOException {
        System.out.println("DelayedReceiver 接受时间: " + LocalDateTime.now() + " msg内容:" + msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
    }
}

 

测试:

@RestController
@RequestMapping("/rabbit")
public class RabbitTest {

    @Autowired
    private DelayedSender delayedSender;


    @GetMapping("/delayedTest")
    public String delayedTest() {
        System.out.println("----延时任务启动成功----");
        delayedSender.send("20秒延时任务-----", 1000*20);
        delayedSender.send("10秒延时任务-----", 1000*10);
        delayedSender.send("5秒延时任务-----", 1000*5);
        return "延时任务启动成功: "+ new Date();
    }
}

 

 

基础配置信息:

rabbitmq:
  host: ${mq.host}
  port: ${mq.port}
  username: ${mq.user}
  password: ${mq.passwd}
  publisher-confirms: true    #消息发送到交换机确认机制,是否确认回调
  publisher-returns: true     #消息失败返回,比如路由不到队列时触发回调
  listener:
    simple:
      acknowledge-mode: manual #设置消费者的手动确认 ack

 

配置全局手动 ack+设置多线程消费者

// 1 在RabbitmqConfig.java添加配置

   @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);//设置手动 ack
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);

        factory.setConcurrentConsumers(10);  //设置线程数
        factory.setMaxConcurrentConsumers(10); //最大线程数
        configurer.configure(factory,connectionFactory);
        return factory;
    }
    @Bean
    public MessageConverter messageConverter() {
        return new ContentTypeDelegatingMessageConverter(new Jackson2JsonMessageConverter());
    }

    @Bean
    public RabbitAdmin rabbitTemplate(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }



//2 在@RabbitListener注解中指定容器工厂
@RabbitListener(queues = {"监听队列名"},containerFactory = "customContainerFactory")


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值