java - RabbitMQ、docker、单队列、多个消费者

标签 java spring docker rabbitmq

我们在我们的系统中使用 Docker、Spring 和 RabbitMq。我是 AMQP 的新手,我试图弄清楚交换、队列、绑定(bind)和连接在我们的系统中是如何工作的。 我们有多个 Docker 化应用程序。

简而言之,当应用程序启动时,它们每个都开始监听同一个队列,我不明白它们如何期望收到相同的消息。 stackoverflow 中也有一些类似的问题,这让我觉得我们当前的系统可能存在缺陷。

更详细:

当docker容器启动时,不同容器中的多个应用程序使用RabbitAdmin来

declare the same exchange: rabbitAdmin.declareExchange(exchange)
declare the same queue: rabbitAdmin.declareQueue(queue)
bind those together: rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(exhange).with("theSameKey");

他们这样做是因为他们想听同样的消息。 据我了解,只有一个 Docker 化程序设法创建交换和队列,其余程序尝试但没有效果。

之后,每个应用程序都会为队列创建并启动 SimpleMessageContainers:

simpleMessageContainer.setMessageListener(messageListener)
simpleMessageContainer.addQueueNames(queue.getName())
simpleMessageContainer.start()

使用rabbitmqctl和rabbitmq的Web界面,我可以看到单个队列在不同的 channel 上有多个消费者,对应于不同的docker容器。

是不是messageListener驻留在应用程序中,但是当调用addQueueNames时,RabbitMq在broker处为队列创建一个Consumer,然后这个Consumer通过连接将消息转发到应用程序本地messageListener?

由于不同 Docker 容器中的多个应用程序执行相同的操作,因此同一个队列有多个消费者,就像我在rabbitmqctl 中看到的那样。

我不明白的是,RabbitMq 是否不会以循环方式将队列中最终的消息传递给 channel /消费者,以便只有一个 Docker 化应用程序会收到它? 交换是直接的、主题类型的,没有扇出交换。 如果所有 Docker 化应用程序都希望接收相同的消息,那么它们不应该都为相同的 exhance 创建一个自己的队列,并使用自己的队列名称和相同的路由键吗?

我看不出当前的实现如何正常工作。

最佳答案

  • 每个容器(实际上是内部运行的应用程序)都会尝试声明交换器和队列。一旦声明,所有其他声明命令都无效(即使参数不同)。

Doesn't RabbitMq pass messages that end up in the queue to the channels/consumers in a round robin fashion.

这是正确的。尽管您可以通过 prefetch_count 和消息 ack 来影响它。

If all the dockerized applications wanted to receive the same message, shouldn't then all of them create an own queue for the same exchange with an own queue name but with the same routing key?

是的,这是唯一的方法,因为根据 AMQP 协议(protocol),消息在消费者之间进行负载平衡。因此,如果所有容器(消费者)要处理相同的消息,则它们每个都应该有不同的队列连接到同一个交换器(直接路由即可)。

无论消费者使用 docker 还是其他方式运行,都是如此。

关于java - RabbitMQ、docker、单队列、多个消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44968010/

相关文章:

java - Text-Adventure 在某一行后意外停止。

java - Java 中的层次结构和数据结构(或 XML 到对象转换 : best practices)

OSGi中的Spring组件扫描什么也没找到

docker - 如何从Docker容器重定向命令输出

postgresql - 如果 ENTRYPOINT 未完成,Dockerfile 不会运行 CMD

linux - 带有 Docker 的 Debian 上的 LibreOffice Online

java - 为什么运行时找不到类?

java - 没有数据源的 Spring Boot + Spring Batch

spring - 如何在 JavaConfig 中定义 http "security = ' none' ?

java - 在一个比较器中对两个不同字段进行排序