【问题标题】:Spring AMQP: how to avoid manual declaration of many queues?Spring AMQP:如何避免手动声明多个队列?
【发布时间】:2014-11-24 15:55:54
【问题描述】:

创建了一个基本的 spring-amqp 设置后,我看到对于我想要发送的每种类型的消息(使用消息 POJO),我需要在 spring 配置中声明队列。

所以对于每一对:

amqpTemplate.convertAndSend("queue1", new MessageType1(...));

@RabbitListener(queues = "queue1")
public void handleMessage(MessageType1 msg) {...}

我需要这样的 spring 配置条目:

<rabbit:queue name="queue1"/>

这对我来说似乎是多余的。如果我想到 HTTP url 之类的队列,那么使用 @RequestMapping("/some-url") 声明控制器就足够了,没有必要在配置的其他地方也声明 /some-url。

如果最终应用程序将有多种类型的消息通过代理,那只会使配置膨胀。

我看到了两种避免这种情况的方法:

  1. 自动为每个带注释的侦听器端点声明队列。即如果有一个带注释的侦听器端点@RabbitListener(queues = "hello"),那么可以推断应该声明一个队列hello。我认为这可能已经是这种情况,但是当我从上下文配置中删除队列时,出现以下错误:

    WARN  BlockingQueueConsumer - Failed to declare queue:hello
    WARN  BlockingQueueConsumer - Queue declaration failed; retries left=2
    org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[hello]
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:479)
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:400)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1022)
    
  2. 在同一个队列上使用不同的消息 POJO。因此,在queue1 上同时发送MessageType1 和MessageType2,每个都根据有效负载类型到达不同的端点。实际上,这会创建一种单一的“应用程序队列”,类似于数据库模式:

    @RabbitListener(queues = "queue1")
    public void handleMessage1(MessageType1 msg) {...}
    
    @RabbitListener(queues = "queue1")
    public void handleMessage2(MessageType2 msg) {...}
    

    尝试这种方法产生了错误。

spring-amqp (1.4.0) 目前是否可以实现上述任何一项,如果可以,如何实现?

【问题讨论】:

  • 你看过Remoting via AMQP吗?它使用您在 (2) 中暗示的机制。我不知道上下文,但这可能对你有用。

标签: java spring spring-amqp


【解决方案1】:

目前无法自动声明 @RabbitListener 队列,但这听起来是一个合理的请求。当然,仅声明队列可能还不够;虽然它将以队列名称作为路由键绑定到默认交换 "",但任何更复杂的绑定无论如何都需要额外的配置。

使用队列名称作为默认交换的路由键不被认为是最佳实践,因为它耦合了生产者和消费者。但我确实知道它有时会被使用,所以请输入New Feature JIRA Issue,我们会考虑的。

顺便说一句,您还可以在侦听器旁边使用@Beans 来避免 XML 配置。

您的第二个请求可以通过委托消息侦听器实现:

@RabbitListener(queues = "queue1")
public void handleMessage(Object o) {
    if (o instanceof Type1) {
        delegate.type1((Type1) o);
    }
    else if (o instanceof Type2) {
        delegate.type2((Type2) o);
    } 
}

我一直在考虑提供这样的监听器(以更通用的方式)。再次,请打开一个新功能问题。

编辑

这两个功能现在都在 1.5 版本中可用。 @QueueBinding 和 Class-level @RabbitListener。

【讨论】:

  • 我开始明白我应该将队列视为更像数据库表而不是 REST URL。如果我们以这种方式考虑它们 - 架构 DDL 文件存在于某处是有意义的。然而,话虽这么说,Hibernate 使用注释我们不会编写这样的 DDL,而是从我们的 POJO 注释中推断出来。也许这里可以采用类似的方法,其中侦听器注释可以提供队列的详细信息。无论如何,我会将讨论转移到 JIRA。
  • 现在可以自动声明了,从 Spring AMQP 1.5.0 开始,目前在 M1 中。见docs.spring.io/spring-amqp/docs/1.5.0.M1/reference/html/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多