通道basicConsume消费者内部类在jrabbitmq ava API中没有GC

时间:2017-08-06 03:03:13

标签: java multithreading rabbitmq rpc spring-rabbitmq

我正在使用rabbitmq rpc来获取多线程环境中的数据,我在下面跟着

  1. 为整个应用程序创建单个连接。
  2. 为每个帖子创建一个频道。
  3. 创建消费者以从每个线程消费并返回。
  4. 问题:

    1. 我的问题是第3次我无法获得一次又一次使用同一消费者的rabbitmq java API。

    2. 如果我让每个频道创建一个消费者,那么该消费者永远不会因为与某个频道相关联的原因而被GC,并且该频道永远不会被删除(设置中的第2点)。但如果我删除每个频道得到GCed。

    3. 可能解决的方法:

      1. 我应该创建并发HashMap并将所有使用者保留在并发Hash Map中并来回加载吗?

      2. rabbit mq basicGet()API:这看起来很混乱:  有时它返回null响应,而rpc-server继续返回正确的值。这里可能的工作是放

        而(真){ //继续投票 //一旦获得数据就中断 }

      3. 这对我来说似乎是个黑客。

        我不认为这里有任何其他选择。

        以下是我用来使用来自rabbit mq rpc的数据的代码:

        public String fetchDataFromRpc(String requestQueueName, byte[] message, Channel channel) throws IOException, InterruptedException {
                final BlockingQueue<String> response = new LinkedBlockingQueue<>();
                String replyQueueName = channel.queueDeclare().getQueue();
                String corrId = UUID.randomUUID().toString();
                System.out.println(" corr id : "+corrId);
                AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().correlationId(corrId).replyTo(replyQueueName).build();
                channel.basicPublish("", requestQueueName, props, message);
                Consumer consumer = new DefaultConsumer(channel) {
                    @Override
                    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                        if (properties.getCorrelationId().equals(corrId)) {
                            response.offer(new String(body, "UTF-8"));
                            channel.queueDelete(replyQueueName);
                            System.out.println(" res corr id : "+corrId);
                        }
                    }
                };
                channel.basicConsume(replyQueueName, true, consumer);
        
                return response.take();
            }
        

        行: channel.basicConsume(replyQueueName,true,consumer); 每次线程进入这个块时都会不断创建新的消费者,旧的消费者永远不会得到GCed,我得到它是因为它链接到通道而不是GCed所以我可以使用HashMap来存储每个线程的所有消费者并从那里继续加载吗?

2 个答案:

答案 0 :(得分:0)

完成后你应该basicCancel()消费者。

但是,您应该进行handleCancel()调用,因为您删除了消费者的队列,因此我不明白为什么消费者不会使用GC。

为每个请求创建临时回复队列效率不高。 RabbitMQ现在提供了一个带有伪回复队列的特殊直接replyTo机制。

为什么要添加代码?我在你的问题中看不到弹簧代码。

另一方面,如果您是春季商店,RabbitTemplate.sendAndReceive()(和convertSendAndReceive())方法将为您处理所有这些(以及it uses direct replyTo, by default, if the broker is new enough)。

答案 1 :(得分:0)

你在谈论下面的事情

@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    if (properties.getCorrelationId().equals(corrId)) {
        response.offer(new String(body, "UTF-8"));
        channel.basicCancel(consumerTag);
        channel.queueDelete(replyQueueName);
    }
}