【问题标题】:How to configure an ActiveMQ Artemis queue not be created again如何配置不再创建 ActiveMQ Artemis 队列
【发布时间】:2021-08-08 21:02:08
【问题描述】:

我有一个没有预配置队列的嵌入式 ActiveMQ Artemis 2.17.0 代理。我希望客户端连接到代理并在它不存在时自动创建它的队列。这在我第一次运行客户端时工作得很好,但在第二次我再次连接到代理时,客户端会抛出一个错误:

errorType=QUEUE_EXISTS message=AMQ229019: Queue hornetq already exists on address router

是否可以将客户端或服务器配置为,如果队列已经存在,则不应尝试再次重新创建它?

以下是我正在运行的程序:

服务器

try {
    ActiveMQServer server = new ActiveMQServerImpl(new ConfigurationImpl()
         .setPersistenceEnabled(true)
         .setBindingsDirectory("./router/data/bindings")
         .setLargeMessagesDirectory("./router/data/large")
         .setPagingDirectory("./router/data/paging")
         .setJournalDirectory("./router/data/journal")
         .setSecurityEnabled(false)
         .addAcceptorConfiguration("tcp", "tcp://0.0.0.0:61617?protocols=CORE,AMQP"));
    server.start();
} catch (Exception ex) {
    System.err.println(ex);
}

客户

ServerLocator serverLocator = ActiveMQClient.createServerLocator("tcp://127.0.0.1.3:61617");
ClientSessionFactory factory = serverLocator.createSessionFactory();
ClientSession session = factory.createSession();
session.createQueue(new QueueConfiguration("router::hornetq")
        .setAutoCreateAddress(Boolean.FALSE)
        .setAutoCreated(Boolean.FALSE)
        .setRoutingType(RoutingType.ANYCAST));
ClientProducer producer = session.createProducer("router::hornetq");
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("Core Queue Message");
producer.send(message);
session.start();
ClientConsumer consumer = session.createConsumer("router::hornetq");
ClientMessage msgReceived = consumer.receive();
System.out.println("message = " + msgReceived.getBodyBuffer().readString());
session.close();

我在这里使用完全限定的队列名称(即router::hornetq),因为router 地址上有多个队列。

【问题讨论】:

    标签: activemq-artemis


    【解决方案1】:

    您的客户端正在使用 core API,这是一个不支持自动队列创建的低级 API。您的客户端正在手动创建(或尝试创建)队列,例如:

    session.createQueue(new QueueConfiguration("router::hornetq")
            .setAutoCreateAddress(Boolean.FALSE)
            .setAutoCreated(Boolean.FALSE)
            .setRoutingType(RoutingType.ANYCAST));
    

    如果队列已经存在,您看到的异常无疑会被抛出这里。创建队列不是幂等的,所以我可以看到 3 个选项:

    • 只需抓住这里抛出的ActiveMQQueueExistsException 并忽略它。
    • 在尝试创建队列之前,使用ClientSession.queueQuery 查看队列是否存在。如果它存在,则不要尝试再次创建它。如果它不存在,则创建它。也就是说,如果您有很多这样的客户端同时运行,由于客户端之间的竞争条件,您仍然有可能获得ActiveMQQueueExistsException
    • 使用支持自动创建的客户端/协议,例如核心 JMS 客户端或 AMQP。

    还有一些值得一提的:

    • 由于您没有显式调用ClientSession.createAddress(),您可能希望使用setAutoCreateAddress(Boolean.TRUE)
    • 您的消费者没有使用router::hornetq。它可以只使用hornetq,它将接收发送到hornetq 队列的任何消息。队列名称在代理中是唯一的。

    【讨论】:

    • 感谢您的及时回复。我想知道核心 API 缺乏幂等性是设计使然,还是可以调查?至于队列名称,我在同一地址下有 2 个队列,因此显式命名。
    • 缺乏幂等性是设计使然,尽管这并不是说设计不能改变。服务器 API 有一个 createQueue 带有一个标志,如果队列已经存在,则忽略该调用。
    • 注明。还有一个问题,我们使用 hornetq 的时间最长,现在我们正在寻求迁移到 artemis。我们使用的是核心 APIS,但我们希望采用 AMQP 以适应更多不同语言的微服务,是否存在显着的性能差异?
    • 这与您最初提出的问题完全不同。我建议您针对核心与 AMQP 性能问题创建一个新问题。
    • 我对可能有用的要点发表了评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多