RabbitMQ DefaultConsumer导致过多的消费者标签

时间:2019-01-18 21:14:54

标签: java rabbitmq amqp rabbitmq-exchange

我有一个RabbitMQ客户端应用程序,它监听特定的队列。客户端创建DefaultConsumer的实例,并实现handleDelivery方法。这是代码

    protected LinkedBlockingQueue<Message> messages = new LinkedBlockingQueue<>();

    public void receiveMessages() {
        try {
//            channel.basicQos(pollCount);
            Message message = new Message();
            Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                        throws IOException {
                    long deliveryTag = envelope.getDeliveryTag();
                    String response = new String(body, "UTF-8");
                    if (response != null) {
                        message.setId(NUID.nextGlobal());
                        message.setPayload(response);
                        message.setDeliveryTag(deliveryTag);
                        messages.add(message);
                        logger.info("Message received: ", message.getPayload());
                    }
                }
            };
            logger.debug("**********Channel status: " + channel.isOpen());
            channel.basicConsume(queueName, false, consumer);
        } catch (Exception e) {
            logger.error("Exception while getting messages from Rabbit ", e);

        }
    }

每500毫秒通过一个线程频繁调用一次方法receiveMessages(),并将消息排放到另一个List中以供使用。由于对receiveMessages()进行了这项民意调查,因此我观察到,通过如图所示的Rabbit控制台进行查看时,消费者标签会不断创建和增长。看到那些不断增长的消费者标签是否正常? enter image description here

3 个答案:

答案 0 :(得分:1)

  

看到那些不断增加的消费者标签是否正常?

否,您的代码有错误。您只需要使用长期运行的使用者,或者在使用完毕后就必须取消其使用者。

我看不到有任何需要“轮询” receiveMessages的需要-只要让它自己运行,它就会按照您的期望将消息添加到同步队列中。


注意: RabbitMQ团队监视rabbitmq-users mailing list,并且有时仅在StackOverflow上回答问题。

答案 1 :(得分:1)

我终于找到了可行的解决方案。 正如Luke Bakken强调的那样,不需要轮询。我现在只打过一次receiveMesssages()。此后,当消息发布到队列中时,我的使用者将收到回调。

 protected LinkedBlockingQueue<Message> messages = new LinkedBlockingQueue<>();
 public void receiveMessages() {
    try {
        Message message = new Message();
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            long deliveryTag = delivery.getEnvelope().getDeliveryTag();
            String response = new String(delivery.getBody(), "UTF-8");
            if (response != null) {
                message.setId(NUID.nextGlobal());
                message.setPayload(response);
                message.setDeliveryTag(deliveryTag);
                messages.add(message);
                logger.info("Message received: ", message.getPayload());
            };
        channel.basicConsume(queueName, false, deliverCallback, consumerTag -> { });
    } catch (Exception e) {
        logger.error("Exception while getting messages from Rabbit ", e);
    }
}

Rabbit控制台现在在绑定队列下仅显示1个消费标签条目。

答案 2 :(得分:0)

public NotificationConsumerService(ConnectionFactory connectionFactory, String host, Logger logger) {
    this.connectionFactory = connectionFactory;
    this.host = host;
    this.logger = logger;
}

public void consumeSliceChangeNotification() {
    connectionFactory.setHost(this.host);
    try (Connection connection = connectionFactory.newConnection();
         Channel channel = connection.createChannel()) {
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            JSONObject obj = new JSONObject(message);
            String namespace = obj.getString("namespace");
            logger.info("The latest change notification on the " + namespace +" is available");
        };

        channel.basicConsume(QUEUE_NAME, true,deliverCallback, consumerTag -> { } );
    } 
    catch (IOException | TimeoutException e) {
        e.printStackTrace();
    }

}