Synchronization 如何将使用者与rabbitmq同步

Synchronization 如何将使用者与rabbitmq同步,synchronization,rabbitmq,synchronous,Synchronization,Rabbitmq,Synchronous,我有以下问题: 我有一个RabbitMQ集群、一个消息生成器和一个消费者集群(用于高可用性)。 每当消费者收到消息时,它都会根据消息内容生成另一个进程并运行它。这个过程相当长,大约需要30分钟 我必须确保每次处理一条消息。但是,消费者比消费者多,因此,如果队列中有2条消息,则一个消费者会收到一条消息,第二个消费者会收到另一条消息,并并行处理这些消息 仅供参考:每个使用者位于不同的计算机中 RabbitMQ级别是否有任何机制允许我等待消费下一条消息,直到前一条消息被确认?或者我必须在服务器之间开发

我有以下问题: 我有一个RabbitMQ集群、一个消息生成器和一个消费者集群(用于高可用性)。 每当消费者收到消息时,它都会根据消息内容生成另一个进程并运行它。这个过程相当长,大约需要30分钟

我必须确保每次处理一条消息。但是,消费者比消费者多,因此,如果队列中有2条消息,则一个消费者会收到一条消息,第二个消费者会收到另一条消息,并并行处理这些消息

仅供参考:每个使用者位于不同的计算机中


RabbitMQ级别是否有任何机制允许我等待消费下一条消息,直到前一条消息被确认?或者我必须在服务器之间开发一些锁定机制吗?

我只是指rabbitmq文档中的几点,我认为它们能够满足您的要求

  • 第一参考-
  • 通常,连接到队列的活动使用者从接收消息 它是以循环的方式进行的。当使用消费者优先级时, 如果存在多个活动使用者,则消息将循环传递 具有相同的高优先级

    我假设您的所有消费者都具有相同的优先级,因此消息将均匀分布到所有活动消费者

  • 第二参考-
  • basic.qos方法允许您限制 消费时通道(或连接)上未确认的消息

    正如您所提到的,您将在一台机器上拥有一个消费者,这将更加容易

    只需将每个使用者的使用者预取限制设置为1。因此,在要求确认之前,服务器将只向消费者发送一条消息。并在消息完全处理后发送基本确认

    Channel channel = ...;
    Consumer consumer = ...;
    channel.basicQos(1); // Per consumer limit
    
    Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
                    System.out.println("received message");
                    // process the message .. time consuming
    
                    // after processing send the basic ack so that next message can be received from queue
                    channel.basicAck(envelope.getDeliveryTag(), false);
            };
    
     channel.basicConsume("my-queue", false, consumer);
    
    我希望这有帮助

    更新-

    再加一点说明- 当你使用

    channel.basicQos(x);
    
    channel.basicQos(x, true);
    
    Rabbitmq将以最大x数量的未确认消息推送到通道上的每个使用者(如果队列中可用,当然是在遵守优先级和循环等之后)。这意味着通道上的每个消费者不会有超过x条未确认的消息,也就是说,消费者可以在任何给定时刻同时处理最多x条消息。消费者发送回ack后,可以将下一条消息推送到消费者。如果消费者感觉无法处理消息,也可以发送nack。在这种情况下,消息将被重新排队,重新排队的消息可能会发送到队列上的任何消费者,具体取决于优先级、循环等

    每个频道可以有多个消费者。所以,当你使用

    channel.basicQos(x);
    
    channel.basicQos(x, true);
    
    限制x适用于整个通道,而不是通道上的单个/每个耗电元件

    在您的情况下,每个频道上只有一个消费者。因此,渠道限制实际上对您的案例没有任何影响

    更多更新-


    计算机通过连接连接到RabbitMQ。一个连接可以有多个通道。一个渠道可以有多个消费者。因此,从逻辑上讲,可以有不同的机器连接到RabbitMQ,并且有多个通道和使用者在同一队列上侦听。您可以同时为两个通道(使用
    channel.basickos(x,true)
    )以及通道内的消费者(使用
    channel.basickos(x,false)
    )设置QOS限制。限制0表示无限制。显然,这些限制适用于通道实例。驻留在不同通道实例(在同一台机器或不同的机器上)上的所有使用者都有自己的限制(默认或QOS方法显式设置)

    正如@vsoni一般解释的那样,我们可以使用基本的QOS,这将允许每个消费者一次消费X条消息,更准确地说是每个通道。由于通道是“共享单个TCP连接的轻量级连接”(请参阅),因此,据我所知,在两台不同机器上运行的两个消费者之间不可能实现QOS。我的目标是,当第一个消费者仍在消费前一个消费者时,不要向第二个消费者发送消息。我只通过外部锁定实现了它(出于开发目的,我在一台机器上创建了一个简单的文件锁和3个使用者),但对于生产,我可能会使用一个。另一种选择是使用Zookeeper、etcd或类似软件的分布式锁定。

    谢谢!不知道我是否理解正确。如果我将QOS设置为1,有两个相同的使用者,则不可能同时使用两条消息?您好,很抱歉回复太晚。谢谢你的解释。我现在看到了QOS是如何工作的,但我正在尝试找出如何将多个消费者连接到一个通道(使用Node.js)。如果我能完成,我会解决问题:)我会更新进度,所以从这里我可以看到:这是不可能的。。通道是TCP连接内部的“虚拟连接”。我不认为我可以使用相同的TCP连接在两台不同的机器上创建两个不同的客户端;)因此,我认为这是不可能的,我将不得不进行一些外部锁定:(在我的回复帖子上添加了一些更新。添加了一些更新。参考此链接-…可能会有所帮助。但只是试图理解…如果你不想让其他消费者(甚至居住在不同的机器上)要在一个消费者仍在处理一条消息时处理一条消息,那么为什么您需要多个消费者。一个消费者应该足够了。我在问题中提到,这是为了高可用性。我们有两个可用性区域(AWS)中的机器,如果其中一个“死亡”,我们仍然希望能够处理消息,但是(不幸的是,由于API的限制)我们不能同时连接两个客户端)。但是感谢所有的信息,这真的很有帮助!