RabbitMQ动态创建消息队列和消费者,消费者上下线

本文章向大家介绍RabbitMQ动态创建消息队列和消费者,消费者上下线,主要包括RabbitMQ动态创建消息队列和消费者,消费者上下线使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

@Component
public class CustomizeDynamicConsumerContainer{
   
   /**
     * 用于存放全局消费者
     */
    public final Map<String, DynamicConsumer> customizeDynamicConsumerContainer= new 
    ConcurrentHashMap<>();
}
public interface IDynamicConsumer extends ChannelAwareMessageListener {

    void setContainer(SimpleMessageListenerContainer container);

    default void shutdown() {}

}
public abstract class mqConsumer implements IDynamicConsumer {
    private volatile boolean end = false;
    private SimpleMessageListenerContainer container;
    private boolean autoAck;

    @Override
    public void setContainer(SimpleMessageListenerContainer container) {
        this.container = container;
        autoAck = container.getAcknowledgeMode().isAutoAck();
    }

    @Override
    public void shutdown() {
        end = true;
    }

    protected void autoAck(Message message, Channel channel, boolean success) throws IOException {
        if (autoAck) {
            return;
        }

        if (success) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } else {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

    public abstract boolean process(Message message, Channel channel);
}
public class DynamicConsumer {


    private static final Logger logger = LoggerFactory.getLogger(DynamicConsumer.class);
    private SimpleMessageListenerContainer container;

    public DynamicConsumer(MQContainerFactory fac, String name) throws Exception {
        SimpleMessageListenerContainer container = fac.getObject();
        container.setMessageListener(new AbsMQConsumer() {
            @Override
            public boolean process(Message message, Channel channel) {
                logger.info("DynamicConsumer,{},{}, {},name,fac.getQueue(),new String(message.getBody())");
                distributionConsumerMsg(message, channel);
                return true;
            }
        });
        this.container = container;
    }

    //启动消费者监听
    public void start() {
        container.start();
    }

   //消费者停止监听
    public void stop() {
        container.stop();
    }

    //消费者重启
    public void shutdown() {
        container.shutdown();
    }


    /**
     * 用户扩展处理消息
     */
    public void distributionConsumerMsg(Message message, Channel channel) {

    }

}
@Data
@Builder
public class DynamicConsumerContainerFactory implements FactoryBean<SimpleMessageListenerContainer> {
    private ExchangeType exchangeType;

    private String directExchange;
    private String topicExchange;
    private String fanoutExchange;

    private String queue;
    private String routingKey;


    private Boolean autoDeleted;
    private Boolean durable;
    private Boolean autoAck;

    private ConnectionFactory connectionFactory;
    private RabbitAdmin rabbitAdmin;
    private Integer concurrentNum;

    // 消费方
    private IMqConsumer consumer;


    private Exchange buildExchange() {
        if (null != directExchange) {
            exchangeType = ExchangeType.DIRECT;
            return new DirectExchange(directExchange);
        } else if (null != topicExchange) {
            exchangeType = ExchangeType.TOPIC;
            return new TopicExchange(topicExchange);
        } else if (null != fanoutExchange) {
            exchangeType = ExchangeType.FANOUT;
            return new FanoutExchange(fanoutExchange);
        } else {
            if (StringUtils.isEmpty(routingKey)) {
                throw new IllegalArgumentException("defaultExchange's routingKey should not be null!");
            }
            exchangeType = ExchangeType.DEFAULT;
            return new DirectExchange("");
        }
    }


    private Queue buildQueue() {
        if (StringUtils.isEmpty(queue)) {
            throw new IllegalArgumentException("queue name should not be null!");
        }

        return new Queue(queue, durable == null ? false : durable, false, autoDeleted == null ? true : autoDeleted);
    }


    private Binding bind(Queue queue, Exchange exchange) {
        return exchangeType.binding(queue, exchange, routingKey);
    }


    private void check() {
        if (null == rabbitAdmin || null == connectionFactory) {
            throw new IllegalArgumentException("rabbitAdmin and connectionFactory should not be null!");
        }
    }


    @Override
    public SimpleMessageListenerContainer getObject() throws Exception {
        check();

        Queue queue = buildQueue();
        Exchange exchange = buildExchange();
        Binding binding = bind(queue, exchange);

        rabbitAdmin.declareQueue(queue);
        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareBinding(binding);

        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setRabbitAdmin(rabbitAdmin);
        container.setConnectionFactory(connectionFactory);
        container.setQueues(queue);
        container.setPrefetchCount(20);
        container.setConcurrentConsumers(concurrentNum == null ? 1 : concurrentNum);
        container.setAcknowledgeMode(autoAck ? AcknowledgeMode.AUTO : AcknowledgeMode.MANUAL);


        if (null != consumer) {
            container.setMessageListener(consumer);
        }
        return container;
    }

    @Override
    public Class<?> getObjectType() {
        return SimpleMessageListenerContainer.class;
    }
}

消费者创建类

public class ConsumerGenerate {

    /**
     * 创建消费者
     *
     * @param connectionFactory
     * @param rabbitAdmin
     * @param exchangeName
     * @param queueName
     * @param routingKey
     * @param autoDelete
     * @param durable
     * @param autoAck
     * @return
     * @throws Exception
     */
    public static DynamicConsumer genConsumer(ConnectionFactory connectionFactory, RabbitAdmin rabbitAdmin,
                                              String exchangeName, String queueName, String routingKey, boolean autoDelete, boolean durable,
                                              boolean autoAck) throws Exception {
        MQContainerFactory fac =
                MQContainerFactory.builder().directExchange(exchangeName).queue(queueName).autoDeleted(autoDelete)
                        .autoAck(autoAck).durable(durable).routingKey(routingKey).rabbitAdmin(rabbitAdmin)
                        .connectionFactory(connectionFactory).build();
        return new DynamicConsumer(fac, queueName);
    }

}
@Configuration
public class MqConfig {


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


    @Bean
    public AmqpProducer amqpProducer(ConnectionFactory connectionFactory) {
        return new AmqpProducer(connectionFactory);
    }

    public class AmqpProducer {

        private AmqpTemplate amqpTemplate;

        public AmqpProducer(ConnectionFactory connectionFactory) {
            amqpTemplate = new RabbitTemplate(connectionFactory);
        }

        /**
         * 将消息发送到指定的交换器上
         *
         * @param exchange
         * @param msg
         */
        public void publishMsg(String exchange, String routingKey, Object msg) {
            amqpTemplate.convertAndSend(exchange, routingKey, msg);
        }
    }
}

//实际业务使用使用方法

@Service
public class TestService {
    @Autowired
    private ConnectionFactory connectionFactory;
    @Autowired
    private RabbitAdmin rabbitAdmin;
    @Autowired
    private CustomizeDynamicConsumerContainer customizeDynamicConsumerContainer;
    @Autowired
    private MqConfig.AmqpProducer amqpProducer


    public void dynamicCreateConsumer(){
        Map<String, DynamicConsumer> allQueue2ContainerMap = customizeDynamicConsumerContainer.customizeDynamicConsumerContainer;
        DynamicConsumer consumer = null;
        try {
            //创建消费者
            consumer = ConsumerGenerate
                    .genConsumer(connectionFactory, rabbitAdmin,"test001-1", "test001", "routingKey001"
                            , false, true, true);
        } catch (Exception e) {
             logger.error("系统异常",e);
        }
        allQueue2ContainerMap.put("test001", consumer);
        //启动消费者
        consumer.start();
        //发送消息到交换机
       amqpProducer.publishMsg("test001-1", "routingKey001", "Hello MQ!");
    }

    /**
     * 暂停消费者
     */
    public void stop(){
        Map<String, DynamicConsumer> allQueue2ContainerMap = customizeDynamicConsumerContainer.customizeDynamicConsumerContainer;
        DynamicConsumer dynamicConsumer = allQueue2ContainerMap.get("test001");
        dynamicConsumer.stop();
    }


}

 

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
RabbitMQ 中,可以通过动态地添加或删除消费者来调整消费者数量。这可以通过以下步骤实现: 1. 创建一个队列,并为其定义一个消费者函数。消费者函数将被用来处理从队列中接收到的消息。 2. 使用 `basic.consume()` 函数将消费者函数绑定到队列上,以便它可以开始接收消息。 3. 创建一个循环,在循环中使用 `basic.qos()` 函数来设置每个消费者可以接收的最大未确认消息数。这可以帮助确保消息在多个消费者之间均匀分配。 4. 在循环中使用 `basic.consume()` 函数创建新的消费者,以响应队列中积压的消息。要删除消费者,可以使用 `basic.cancel()` 函数。 以下是一个示例代码片段,演示如何动态调整消费者数量: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() queue_name = 'my_queue' def callback(ch, method, properties, body): print("Received message: %s" % body) channel.queue_declare(queue=queue_name) channel.basic_consume(queue=queue_name, on_message_callback=callback) # Set the maximum number of unacknowledged messages per consumer channel.basic_qos(prefetch_count=1) while True: # Get the current number of consumers consumers = len(channel._consumer_infos) # If there are fewer than 3 consumers, add one more if consumers < 3: channel.basic_consume(queue=queue_name, on_message_callback=callback) # If there are more than 3 consumers, remove one elif consumers > 3: channel.basic_cancel(consumer_tag=channel._consumer_infos.keys()[0]) ``` 这个示例代码片段将队列名 `my_queue` 绑定到一个消费者函数 `callback()` 上。每个消费者最多可以接收 1 条未确认消息。然后,它进入一个无限循环,检查当前消费者数量。如果消费者少于 3,它将创建一个新的消费者,并将其绑定到队列上。如果消费者多于 3,它将删除一个消费者。 请注意,这只是一个示例,实际应用中可能需要更复杂的逻辑来确定何时添加或删除消费者

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值