gpt4 book ai didi

java - 在向其发布消息之前确保 AMQP 交换存在

转载 作者:行者123 更新时间:2023-12-02 01:38:19 25 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它.

6年前关闭。




Improve this question




问题

Java 应用程序使用 RabbitMQ 和客户端库 com.rabbitmq:amqp-client连接到它。应用程序在初始化期间声明 AMQP 交换并定期向其发布消息。

如果由于某种原因该交换被删除,则应用程序无法向其发布消息,并且 AMQP channel 会被库 自动关闭。 .因此,任何后续发布(即使在重新创建交换之后)都会失败,但会出现以下异常:

Exception in thread "main" com.rabbitmq.client.AlreadyClosedException: channel is already closed due to channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'logs' in vhost '/', class-id=60, method-id=40)
at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:195)
at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:296)
at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:648)
at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:631)
at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:622)

我如何保证在发布之前交换确实存在?我看到以下选项。

可能的解决方案

1.尝试在每次显式发布前重新声明exchange

感谢 exchangeDeclare是幂等的并且如果交换已经到位则无效我可以在任何发布之前明确声明交换:
channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false, true, null);
channel.basicPublish(EXCHANGE_NAME, "", MessageProperties.PERSISTENT_TEXT_PLAIN, message);

这段代码的问题是它看起来很愚蠢,因为大多数时候交换已经到位并且声明只是多余的。

另外,如果在声明和发布之间完全删除了交换,我仍然会遇到麻烦。

2. 通过 exchangeDeclarePassive 验证交换是否存在

我可以使用 exchangeDeclarePassive在发布之前检查交换是否存在,但以下明显的方法不起作用:
private static void ensureExchangeExists(Channel channel) throws IOException {
try {
channel.exchangeDeclarePassive(EXCHANGE_NAME);
} catch (Exception e) {
channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false, true, null);
}
}

问题是如果交换丢失, exchangeDeclarePassive抛出异常,库自动关闭 channel 。所以 catch block 中的代码不能声明交换(因为它试图在关闭的 channel 上执行操作)。

所以我不能再使用单个 AMQP channel ,必须以某种方式管理它们。

如果在声明和发布之间删除交换,我仍然有麻烦。

3. 发布时捕获异常

您不能只用 try/catch block 包装调用 channel.basicPublish,因为如果交换丢失,则不会引发异常。 This answer解释在这种情况下实际发生的情况。

但是你可以注册一个 ShutdownListener能够检测 channel 何时关闭,调查原因(通过 cause.isInitiatedByApplication()/ cause.getReason() )并采取必要的措施。

问题

问题是在向它发布消息之前确保 AMQP 交换存在的最佳方法是什么,为什么?

最佳答案

IME,选项#1 是接近更好的选项。

我发现最有效的方法是将给定发布者的代码以一种允许我在第一次创建对象实例时声明/重新声明队列的方式封装。然后我可以重复使用相同的对象实例来发布消息,而无需再次重新声明交换。

如果我创建对象的新实例,它将重新声明交换。但是重新使用相同的实例可以防止这种情况发生。

这个策略对我来说效果很好。

另一种选择是在应用启动时预先定义和预先声明您的交换、队列和绑定(bind)。这样你就不必再担心了。这里的缺点是你已经预先确定了所有的交换、队列和绑定(bind)......这在某些应用程序中有效,但在其他应用程序中无效。

关于java - 在向其发布消息之前确保 AMQP 交换存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32055259/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com