Java RabbitMQ DefaultConsumer导致消费者标记过多

Java RabbitMQ DefaultConsumer导致消费者标记过多,java,rabbitmq,amqp,rabbitmq-exchange,Java,Rabbitmq,Amqp,Rabbitmq Exchange,我有一个RabbitMQ客户端应用程序,它侦听特定队列。客户端创建DefaultConsumer的实例并实现handleDelivery方法。这是密码 protected LinkedBlockingQueue<Message> messages = new LinkedBlockingQueue<>(); public void receiveMessages() { try { // channel.basicQ

我有一个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);

        }
    }
受保护的LinkedBlockingQueue消息=新建LinkedBlockingQueue();
public void receiveMessages(){
试一试{
//信道基本频率(pollCount);
消息消息=新消息();
消费者=新的默认消费者(频道){
@凌驾
public void handleDelivery(字符串consumerTag、信封信封、AMQP.BasicProperties属性、字节[]正文)
抛出IOException{
long deliveryTag=envelope.getDeliveryTag();
字符串响应=新字符串(正文,“UTF-8”);
if(响应!=null){
message.setId(NUID.nextGlobal());
message.setPayload(响应);
message.setDeliveryTag(deliveryTag);
消息。添加(消息);
logger.info(“收到的消息:”,Message.getPayload());
}
}
};
logger.debug(“*******通道状态:”+Channel.isOpen());
channel.basicConsume(queueName,false,consumer);
}捕获(例外e){
logger.error(“从Rabbit获取消息时出现异常”,e);
}
}
方法receiveMessages()每500毫秒通过一个线程频繁调用一次,并将消息排入另一个列表以供使用。由于这次对receiveMessages()的调查,我观察到消费者标签在通过兔子控制台(如图所示)查看时不断创建和增长。看到越来越多的消费者标签是正常的吗?

看到越来越多的消费者标签是正常的吗

不,您的代码有错误。您需要使用一个长期运行的消费者,或者在使用完消费者后必须取消它

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


注意:RabbitMQ团队监控
RabbitMQ用户
,并且有时只回答有关StackOverflow的问题

看到越来越多的消费者标签是正常的吗

不,您的代码有错误。您需要使用一个长期运行的消费者,或者在使用完消费者后必须取消它

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



注意:RabbitMQ团队监视
RabbitMQ用户
,有时只回答有关StackOverflow的问题。

我终于找到了一个有效的解决方案。 正如Luke Bakken强调的,不需要投票。我现在只调用了
receiveMessages()
一次。此后,当消息发布到队列中时,我的消费者将收到回调

 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);
    }
}
受保护的LinkedBlockingQueue消息=新建LinkedBlockingQueue();
public void receiveMessages(){
试一试{
消息消息=新消息();
DeliverCallback DeliverCallback=(消费者标记,交货)->{
long deliveryTag=delivery.getEnvelope().getDeliveryTag();
字符串响应=新字符串(delivery.getBody(),“UTF-8”);
if(响应!=null){
message.setId(NUID.nextGlobal());
message.setPayload(响应);
message.setDeliveryTag(deliveryTag);
消息。添加(消息);
logger.info(“收到的消息:”,Message.getPayload());
};
basicConsume(queueName,false,deliverCallback,consumerTag->{});
}捕获(例外e){
logger.error(“从Rabbit获取消息时出现异常”,e);
}
}

兔子控制台现在只显示绑定队列下的一个消费标签条目。

我终于找到了一个有效的解决方案。 正如Luke Bakken强调的,不需要轮询。我现在只调用一次
receiveMessages()
。此后,当消息发布到队列中时,我的消费者将收到回调

 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);
    }
}
受保护的LinkedBlockingQueue消息=新建LinkedBlockingQueue();
public void receiveMessages(){
试一试{
消息消息=新消息();
DeliverCallback DeliverCallback=(消费者标记,交货)->{
long deliveryTag=delivery.getEnvelope().getDeliveryTag();
字符串响应=新字符串(delivery.getBody(),“UTF-8”);
if(响应!=null){
message.setId(NUID.nextGlobal());
message.setPayload(响应);
message.setDeliveryTag(deliveryTag);
消息。添加(消息);
logger.info(“收到的消息:”,Message.getPayload());
};
basicConsume(queueName,false,deliverCallback,consumerTag->{});
}捕获(例外e){
logger.error(“从Rabbit获取消息时出现异常”,e);
}
}
兔子控制台现在只显示绑定队列下的1个消费标记条目。

公共通知ConsumerService(ConnectionFactory ConnectionFactory、字符串主机、记录器){
this.connectionFactory=连接工厂;
this.host=host;
this.logger=记录器;
}
公共无效更改通知(){
connectionFactory.setHost(this.host);
try(Connection=connectionFactory.newConnection();
Channel=connection.createChannel()){
channel.queueDeclare(队列名称,false,false,false,null);
DeliverCallback DeliverCallback=(消费者标记,交货)->{
字符串消息=新字符串(delivery.getBody(),“UTF-8”);
JS