RabbitMQ:动态增减监听队列

rabbitmq可以动态的增减监听队列,目前我想到的使用场景是:

      当有消息积压,或者预计不久的将来的某一段时间内,会有大量的消息需要消费时,可以增加监听队列,当恢复平常时候就减少监听队列。

先看消费者工程的配置:

@Configuration
public class MessageListenerConfig {

    @Autowired
    private CachingConnectionFactory connectionFactory;

    @Autowired
    private MyAckReceiver myAckReceiver;//消息接收处理类

    @Bean
    public SimpleMessageListenerContainer simpleMessageListenerContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setConcurrentConsumers(1);
        container.setMaxConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息
        //设置一个队列
        container.setQueueNames(FanoutRabbitmqConfig.EMAIL_QUEUE,FanoutRabbitmqConfig.SMS_QUEUE,
                RoutingRabbitmqConfig.EMAIL_QUEUE,RoutingRabbitmqConfig.SMS_QUEUE,
                TopicsRabbitmqConfig.EMAIL_QUEUE,TopicsRabbitmqConfig.SMS_QUEUE
                ,DeadLetterConfig.QUEUE_DEAD,DeadLetterConfig.QUEUE_NORMAL);
        container.setMessageListener(myAckReceiver);

        return container;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(){
        return new RabbitAdmin(connectionFactory);
    }
}
  • SimpleMessageListenerContainer:用来动态设置要监听的队列
  • RabbitAdmin:用来设置新增队列与交换机的绑定关系
  • MyAckReceiver:消息处理类,实现了ChannelAwareMessageListener接口

 MyAckReceiver的实现如下:

@Component
public class MyAckReceiver implements ChannelAwareMessageListener {

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            String consumerQueue = message.getMessageProperties().getConsumerQueue();
            String msg = new String(message.getBody());
            System.out.println("MyAckReceiver的 "+consumerQueue+" 队列,收到消息 "+msg);
            channel.basicAck(deliveryTag, true);
        } catch (Exception e) {
            channel.basicReject(deliveryTag, false);
            e.printStackTrace();
        }
    }
}

提供动态增减监听队列的接口:

@RestController
public class QueueController {
    @Autowired
    private SimpleMessageListenerContainer listenerContainer;

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Resource
    private DirectExchange getDirectExchange;

    private static final String ROUTING_KEY = "dynamic_queue";

    @PostMapping("/queue/{queueName}")
    public String addQueue(@PathVariable String queueName){
        Queue queue = new Queue(queueName);
        rabbitAdmin.declareQueue(queue);
        listenerContainer.addQueues(queue);
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(getDirectExchange).with(ROUTING_KEY));
        return "增加监听队列:"+queueName+" 成功";
    }

    @DeleteMapping("/queue/{queueName}")
    public String deleteQueue(@PathVariable String queueName){
        listenerContainer.removeQueueNames(queueName);
//        rabbitAdmin.deleteQueue(queueName);
        return "移除监听队列:"+queueName+" 成功";
    }
}

生产者工程只需要调用相应的接口就可以了,这里使用的是RestTemplate通过http调用,生产实践很大可能是通过feign调用:

@RestController
public class DynamicQueueController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    private static RestTemplate restTemplate = new RestTemplate();

    private static final String ROUTING_KEY = "dynamic_queue";

    @GetMapping("/addQueue")
    public String addQueue(String queueName){
        String url = "http://192.168.231.1:8888/queue/" + queueName;
        return restTemplate.postForObject(url,null,String.class);
    }

    @GetMapping("/push/{msg}")
    public String pushMsg(@PathVariable String msg){
        rabbitTemplate.convertAndSend(RoutingRabbitmqConfig.EXCHANGE_NAME,ROUTING_KEY,msg);
        return "发送成功";
    }

    @GetMapping("/deleteQueue")
    public String deleteQueue(String queueName){
        String url = "http://192.168.231.1:8888/queue/" + queueName;
        restTemplate.delete(url);
        return "删除队列成功";
    }
}

示例代码地址:GitHub - qiuxinfa/rabbitmq-study

你可能感兴趣的:(rabbitmq,rabbitmq)