Rabbitmq 多线程应用程序中的Rabbit MQ同步发送和接收
我有一个多线程的spring应用程序,我在其中创建主题交换、声明队列、用路由键绑定它们。同步发送和接收消息。我能够将消息发送到主题交换,并看到消息通过routingKey发布到队列中 然而,在接收消息时,我看到消费者在每次迭代中都注册了队列,而没有取消注册。我正在创建QueueingConsumer以接收消息,可能还有其他方法可以做到这一点,请让我知道。下面是receiveMessage方法的代码段Rabbitmq 多线程应用程序中的Rabbit MQ同步发送和接收,rabbitmq,spring-amqp,Rabbitmq,Spring Amqp,我有一个多线程的spring应用程序,我在其中创建主题交换、声明队列、用路由键绑定它们。同步发送和接收消息。我能够将消息发送到主题交换,并看到消息通过routingKey发布到队列中 然而,在接收消息时,我看到消费者在每次迭代中都注册了队列,而没有取消注册。我正在创建QueueingConsumer以接收消息,可能还有其他方法可以做到这一点,请让我知道。下面是receiveMessage方法的代码段 public ObjectMessage receiveMessage(final String
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)
{
}
}
}
通过你的编辑,你完全改变了你的问题;你最初的问题说你被绞死了。如果您使用的是Spring AMQP,为什么不使用其更高级别的抽象呢?您永远不会取消您的消费者-您需要跟踪basicConsume返回的消费者标记,并在完成后与basicCancel一起取消它。您所描述的对我来说毫无意义;请提供更多的细节堆栈跟踪等。如果你可以发布一个复制它的示例应用程序,例如Gist,那就更好了。提供了示例代码的更多细节,很抱歉完全更改了这个问题,因为我对与主题和扇出交换相关的AMQP概念没有多少了解,因此产生了一些混乱。通过更高级别的抽象,您是指使用RabbitTemplate发送和接收方法吗?是的,以及异步接收的消息侦听器容器。消费者列表立即删除。非常感谢你,加里。您是一位伟大的导师。我已经使用异步SimpleMessageListenerContainer实现了该系统,一切都很好。现在,我想使用同步发送和接收来查看两种方法在我们的系统中的性能差异及其优缺点。