动态更新basic_qos预取以防止在工作人员保持忙碌之后预取消息

时间:2017-12-06 16:38:43

标签: multithreading rabbitmq amqp multiprocess

我正在寻找性能问题或围绕动态调整预取计数的其他问题。当然,我也欢迎更好的解决方案。

在我的场景中,我有10个工作线程,我的消费者会向其分发消息。当然,我的预取数为10,这样他们就可以同时接收工作。

如果我想早点确认消息并在worker中执行更长时间的运行任务,那么这是一个问题。当我的工作人员开始做更多工作时,Rabbit将预取下一个头部消息,可能导致该消息被延迟,而其他工作人员(在一个完全不同的过程中)可以处理它。

我正在想象一个解决方案,我的消费者在将消息分发给工作人员之前递减预取计数,然后在工作人员完成后再次递增它。

总结问题&建议的解决方案:

工作人员在收到消息后可能无法立即使用,导致下一条预取消息被不必要地延迟。

向工作人员分发消息的消费者可以根据独立工作人员的业务调整预取计数。

1 个答案:

答案 0 :(得分:1)

它看起来像性能调整方案。你需要了解

  1. 一段时间内的消息频率。
  2. 处理时间(工作线程在处理消息时花费的时间)差异。每条消息的处理时间是否相同或不均匀。
  3. 您可以做的一个逻辑解决方案是(如果您能够识别等待处理消息的工作线程数)您将预取计数重置为可用线程数并将基本确认发送到rabbitmq。即在每个工作线程处理完成后(即工作线程可用),您发送这些

    channel.basicQos(no_of_available_worker_threads); 
    channel.basicAck(envelope.getDeliveryTag(), false);
    

    <强> e.g。假设一个场景 您刚开始使用预取限制10.您已收到4条消息。所以现在有4个工作线程忙于处理消息。然后,您完成一个处理并可用于下一条消息。此时你有7个工作线程在等待。现在,您将发送

    channel.basicQos(7); 
    channel.basicAck(envelope.getDeliveryTag(), false);
    

    现在,您的消费者会收到来自rabbitmq的3条消息。你现在有4个工作线程在等待。现在又有一个工作线程可用了。现在,您将发送

    channel.basicQos(5); 
    channel.basicAck(envelope.getDeliveryTag(), false);
    

    一段时间后,再有一个线程可用。现在,您将发送

    channel.basicQos(4); 
    channel.basicAck(envelope.getDeliveryTag(), false);
    

    依旧......

    因此,您的消费者在此刻将永远不会收到比可用工作人员更多的消息。

    更新 -

    我不确定您使用的是哪种语言客户端。但是,如果您使用的是Java客户端(我使用amqp-client5.0.0.jar进行了测试),则消费者(在下面的代码中创建)总是在收到新消息时创建一个新线程,在处理消息后线程被销毁。您不必管理线程以并行处理消息。因此,在任何给定时间,您将永远不会拥有比您设置的QOS限制更多的线程。

    Consumer consumer = new DefaultConsumer(channel) {
                  @Override
                  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                      throws IOException {
                    String message = new String(body, "UTF-8");
                    System.out.println("Received '" + message + "'");
                    //process message
            };
    channelSet.basicConsume(queueName, true, consumer);