简体   繁体   English

Symfony Messenger 顺序消息处理和 RabbitMQ 上的 x-single-active-consumer 参数

[英]Symfony Messenger sequential message processing and the x-single-active-consumer argument on RabbitMQ

I use Symfony Messenger with the RabbitMQ adapter in my application.我在我的应用程序中使用 Symfony Messenger 和 RabbitMQ 适配器。 The logic of the application is that messages from the same queue must be executed sequentially, one after the other (the order is not important), even if the queue is listened to by multiple consumers.应用程序的逻辑是,来自同一个队列的消息必须按顺序执行,一个接一个(顺序不重要),即使该队列被多个消费者监听。 In other words, the queue should not give out other messages if at least one is unacked.换句话说,如果至少有一条消息未被确认,则队列不应发出其他消息。

To solve the problem, I found in the documentation an option such as x-single-active-consumer ( https://www.rabbitmq.com/consumers.html#single-active-consumer ).为了解决这个问题,我在文档中找到了一个选项,例如 x-single-active-consumer ( https://www.rabbitmq.com/consumers.html#single-active-consumer )。

The configuration is like this:配置是这样的:

  my-queue:
    dsn: amqp://guest:guest@localhost:5672/%2f/my-queue
    options:
      queues:
        my-queue:
          arguments:
            x-single-active-consumer: true

The UI shows that the queue was created with the SAC (single-active-consumer) flag, which confirms that the configuration is correct. UI 显示队列是使用 SAC(single-active-consumer)标志创建的,这确认了配置是正确的。 However, when several consumers are started, they receive tasks in parallel, without waiting for the previous task to finish, in fact, as if the single-active-consumer flag wasn't set at all.然而,当多个消费者启动时,它们并行接收任务,而不是等待前一个任务完成,事实上,就好像根本没有设置单活动消费者标志一样。

Can you tell me what I'm doing wrong?你能告诉我我做错了什么吗?

Preconditions:前提条件:

  • symfony/messenger 4.4.* symfony/信使 4.4.*
  • RabbitMQ 3.8 + RabbitMQ 3.8 +

Only what I needed to do was to remove queue in Rabbit Admin and let consumer to register new one.只有我需要做的是在 Rabbit Admin 中删除队列并让消费者注册新的。

It is not possible to enable single active consumer with a policy.无法使用策略启用单个活动消费者。 Here is the reason why.这就是原因。 Policies in RabbitMQ are dynamic by nature, they can come and go, enabling and disabling the features they declare. RabbitMQ 中的策略本质上是动态的,它们可以出现在 go 中,启用和禁用它们声明的功能。 Imagine suddenly disabling single active consumer on a queue: the broker would start sending messages to inactive consumers and messages would be processed in parallel, exactly the opposite of what single active consumer is trying to achieve.想象一下突然禁用队列上的单个活动消费者:代理将开始向非活动消费者发送消息,并且消息将被并行处理,这与单个活动消费者试图实现的完全相反。 As the semantics of single active consumer do not play well with the dynamic nature of policies, this feature can be enabled only when declaring a queue, with queue arguments由于单个活动消费者的语义不能很好地适应策略的动态特性,因此只能在声明队列时启用此功能,队列 arguments

https://www.rabbitmq.com/consumers.html#single-active-consumer https://www.rabbitmq.com/consumers.html#single-active-consumer

You can verify setup from rabbitmq container (or to use rabbitmqadmin whenever you have your rabbit)您可以从rabbitmq 容器验证设置(或在您拥有兔子时使用rabbitmqadmin

rabbitmqadmin export rabbit.definitions.json
...
"queues": [
    {
        "name": "some-queue",
        "vhost": "/",
        "durable": true,
        "auto_delete": false,
        "arguments": {
            "x-single-active-consumer": true <--------------
        }
    }
],
"exchanges": [
    {
        "name": "my-exchange",
        "vhost": "/",
        "type": "direct", <---------------------------------
        "durable": true,
        "auto_delete": false,
        "internal": false,
        "arguments": {}
    }
}
...

edit #1: You many also want to check that exchange is type of direct .编辑#1:你们很多人还想检查交换是direct的类型。 Default by symfony/messenger is fanout , which distributes messages to all available consumers. symfony/messenger默认是fanout ,它将消息分发给所有可用的消费者。

The fanout exchange is very simple.扇出交换非常简单。 As you can probably guess from the name, it just broadcasts all the messages it receives to all the queues it knows.正如您可能从名称中猜到的那样,它只是将收到的所有消息广播到它知道的所有队列。

https://www.rabbitmq.com/tutorials/tutorial-three-python.html https://www.rabbitmq.com/tutorials/tutorial-three-python.html

config/messenger.yml

...
my-binding:
    dsn: 'some-dsn'
    options:
        exchange:
           name: my-echange
           type: direct

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM