Rabbit MQ在多线程应用程序中同步发送和接收

时间:2014-06-18 18:04:30

标签: rabbitmq spring-amqp

我有一个多线程spring应用程序,我在其中创建主题交换,声明队列,使用路由键绑定它们。同步发送和接收消息。我能够将消息发送到主题交换,并查看使用routingKey发布到队列的消息。

然而,在收到消息时,我看到消费者在每次迭代时都注册了队列而没有注销。我正在创建QueueingConsumer来接收消息,可能还有其他方法可以做同样的事情,请告诉我。以下是receiveMessage方法的代码段。

public ObjectMessage receiveMessage(final String readQueue, final UUID correlationId, final boolean isBroadcastMessage, final int readTimeout, final int readAttempts) 
{
    this.configurationLock.lock();
    this.transmissionSemaphore.release(1);
    this.configurationLock.unlock();
    try
    {
        for (int i = 0; i < readAttempts; i++)
        {
            ObjectMessage returnValue = null;
            try
            {
                returnValue = this.receiveMessage(readQueue, correlationId, isBroadcastMessage, readTimeout);
            }
            catch (final Exception e)
            {
                logger.error(e);
            }
            if (returnValue != null)
            {
                logger.warn("Message received from queue - " + readQueue);
                return returnValue;
            }
        }
        if (correlationId != null)
        {
            throw new MessageNotFoundException(correlationId);
        }
        return null;
    }
    finally
    {
        try
        {
            this.transmissionSemaphore.acquire(1);
        }
        catch (final InterruptedException e)
        {
            Thread.interrupted();
        }
    }
}


private ObjectMessage receiveMessage(final String routingKey, final UUID correlationId, final boolean isBroadcastMessage, final int readTimeout) throws Exception
{
    logger.debug("receiveMessage - routingKey:" + routingKey + ",correlationId:" + correlationId + ",isBroadcastMessage:" + isBroadcastMessage + ",readTimeout:"
            + readTimeout);
    this.configurationLock.lock();
    this.transmissionSemaphore.release(1);
    this.configurationLock.unlock();

    Connection connection = null;
    Channel channel = null;
    QueueingConsumer consumer = null;
    try
    {
        // Binding the topic exchange with queue using routing key
        final String queueName = "clientConfigurationQueue";
        final CachingConnectionFactory cachingConnectionFactory = this.getCachingConnectionFactory(routingKey);
        if (isBroadcastMessage)
        {
            this.declareTopicAmqpInfrastructure(cachingConnectionFactory, routingKey, queueName);
        }
        QueueingConsumer.Delivery delivery;

        connection = cachingConnectionFactory.createConnection();
        channel = connection.createChannel(false);

        consumer = new QueueingConsumer(channel);

        if (correlationId == null)
        {
            channel.basicConsume(queueName, true, consumer);
            delivery = consumer.nextDelivery(readTimeout);
        }
        else
        {
            channel.basicConsume(queueName, false, consumer);
            while (true)
            {
                delivery = consumer.nextDelivery(readTimeout);
                if (delivery != null)
                {
                    final String correlationId = delivery.getProperties().getCorrelationId();

                    if (correlationId.equals(correlationId))
                    {
                        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                        break;
                    }
                    else
                    {
                        channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, true);
                    }
                }
                else
                {
                    break;
                }
            }
        }

        ObjectMessage objectMessage = null;
        if (delivery != null)
        {
            logger.debug("Message received with correlationId - " + delivery.getProperties().getCorrelationId() + " for queue - " + queueName);
            logger.debug("Message received with Body - " + SerializationUtils.deserialize(delivery.getBody()));
            objectMessage = new ObjectMessage();
            objectMessage.setCorrelationId(delivery.getProperties().getCorrelationId());
            objectMessage.setMessage(delivery.getBody());
        }
        else
        {
            logger.debug("Message not received from queueName - " + queueName);
        }

        return objectMessage;
    }
    catch (final IOException | ShutdownSignalException | ConsumerCancelledException | InterruptedException e)
    {
        logger.error("Unable to receive message - " + e);
        throw new Exception(e);
    }
    finally
    {
        try
        {
            this.transmissionSemaphore.acquire(1);
        }
        catch (final InterruptedException e)
        {
            Thread.interrupted();
        }

        try
        {
            if (connection != null)
            {
                connection.close();
            }

            if (channel != null)
            {
                channel.close();
            }
        }
        catch (final Exception ignore)
        {

        }
    }
}

private void declareTopicAmqpInfrastructure(final CachingConnectionFactory cachingConnectionFactory, final String routingKey, String queueName)
{
    final Connection connection = cachingConnectionFactory.createConnection();
    final Channel channel = connection.createChannel(false);
    try
    {
        channel.exchangeDeclare("topicExchange", ExchangeTypes.TOPIC, true, false, null);
        channel.queueDeclare(queueName, true, false, false, null);
        channel.queueBind(queueName, "topicExchange", routingKey);
    }
    catch (final IOException e)
    {
        logger.error("Unable to declare rabbit queue, exchange and binding - " + e);
    }
    finally
    {
        connection.close();
        try
        {
            channel.close();
        }
        catch (final IOException ignore)
        {

        }
    }
}

1 个答案:

答案 0 :(得分:0)

通过编辑,您完全改变了自己的问题;你原来的问题说你被createConnection()挂了。如果您使用的是Spring AMQP,为什么不使用更高级别的抽象?您永远不会取消您的消费者 - 您需要跟踪basicConsume返回的consumerTag,并在完成后使用basicCancel取消它。