Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache kafka Samza:将消息处理延迟到时间戳_Apache Kafka_Message Queue_Apache Samza - Fatal编程技术网

Apache kafka Samza:将消息处理延迟到时间戳

Apache kafka Samza:将消息处理延迟到时间戳,apache-kafka,message-queue,apache-samza,Apache Kafka,Message Queue,Apache Samza,我正在和Samza一起处理卡夫卡主题的消息。有些消息将来会带有时间戳,我想将处理推迟到时间戳之后。同时,我想继续处理其他传入的消息 我试图做的是让我的任务对消息进行排队,并实现WindowableTask,以定期检查消息的时间戳是否允许处理它们。基本思想如下所示: public class MyTask implements StreamTask, WindowableTask { private HashSet<MyMessage> waitingMessages = n

我正在和Samza一起处理卡夫卡主题的消息。有些消息将来会带有时间戳,我想将处理推迟到时间戳之后。同时,我想继续处理其他传入的消息

我试图做的是让我的任务对消息进行排队,并实现WindowableTask,以定期检查消息的时间戳是否允许处理它们。基本思想如下所示:

public class MyTask implements StreamTask, WindowableTask {

    private HashSet<MyMessage> waitingMessages = new HashSet<>();

    @Override
    public void process(IncomingMessageEnvelope incomingMessageEnvelope, MessageCollector messageCollector, TaskCoordinator taskCoordinator) {
        byte[] message = (byte[]) incomingMessageEnvelope.getMessage();
        MyMessage parsedMessage = MyMessage.parseFrom(message);

        if (parsedMessage.getValidFromDateTime().isBeforeNow()) {
            // Do the processing
        } else {
            waitingMessages.add(parsedMessage);
        }

    }

    @Override
    public void window(MessageCollector messageCollector, TaskCoordinator taskCoordinator) {
        for (MyMessage message : waitingMessages) {
            if (message.getValidFromDateTime().isBeforeNow()) {
                // Do the processing and remove the message from the set
            }
        }
    }
}

这显然有一些缺点。当我重新部署任务时,我会在内存中丢失等待的消息。所以我想知道用Samza延迟消息处理的最佳实践。我是否需要一次又一次地将消息重新发送到同一主题,直到我最终能够处理它们?我们正在讨论将处理延迟几分钟,最多1-2小时

在处理消息队列时,重要的是要记住,它们在系统中执行非常特定的功能:当处理器忙于处理前面的消息时,它们保存消息。预期正常运行的消息队列将按需传递消息。这意味着,一旦消息到达队列的头部,队列上的下一次拉动将产生消息

请注意,延迟不是等式的可配置部分。相反,延迟是具有队列的系统的输出变量。事实上,它提供了一些有趣的见解


因此,在一个需要延迟的系统中,例如,加入/等待并行操作完成,您应该考虑其他方法。通常,在这个特定实例中,可查询数据库是有意义的。如果您发现自己将消息保留在队列中一段预先设置的时间,那么您实际上是在将消息队列用作数据库—这不是设计用来提供的功能。这不仅有风险,而且很可能会损害message broker的性能。

我认为您可以使用Samza的键值存储来保存任务实例的状态,而不是在内存中设置。 它应该看起来像:

public class MyTask implements StreamTask, WindowableTask, InitableTask {

  private KeyValueStore<String, MyMessage> waitingMessages;


  @SuppressWarnings("unchecked")
  @Override
  public void init(Config config, TaskContext context) throws Exception {
    this.waitingMessages = (KeyValueStore<String, MyMessage>) context.getStore("messages-store");
  }

  @Override
  public void process(IncomingMessageEnvelope incomingMessageEnvelope, MessageCollector messageCollector,
      TaskCoordinator taskCoordinator) {
    byte[] message = (byte[]) incomingMessageEnvelope.getMessage();
    MyMessage parsedMessage = MyMessage.parseFrom(message);

    if (parsedMessage.getValidFromDateTime().isBefore(LocalDate.now())) {
      // Do the processing
    } else {
      waitingMessages.put(parsedMessage.getId(), parsedMessage);
    }

  }

  @Override
  public void window(MessageCollector messageCollector, TaskCoordinator taskCoordinator) {
    KeyValueIterator<String, MyMessage> all = waitingMessages.all();
    while(all.hasNext()) {
      MyMessage message = all.next().getValue();
      // Do the processing and remove the message from the set
    }
  }

}
若重新部署,任务Samza应重新创建键值存储的状态Samza将值保留在与键值存储相关的特殊kafka主题中。当然,您需要在上面的示例中为messages store提供一些额外的存储配置

您可以在此处阅读有关最新Samza版本的键值存储: