建议在Kafka Streams应用程序中启动新线程(使用程序方式)吗?

时间:2019-05-28 21:52:59

标签: java apache-kafka apache-kafka-streams

我们正在使用低级处理器API开发Kafka Streams应用程序。

根据Kafka上的文档,所有线程和并行性均由Stream线程和流任务处理。并行性还可以使用主题上的分区来扩展。

当前代码如下:

public class Processor implements Processor<K, V> {

@Override
  public void process(String key, V value) {

      //Do processing on the stream thread itself
      ...

      // Write back to output topic
      context.forward(key, updatedValue)
    }); 
  }
}

但是,建议在任何情况下都创建自己的线程来进行实际处理吗?这将意味着主要利用Kafka Streams API来消耗主题中的数据,而不是进行实际处理。实际的处理将发生在Kafka流线程中的初始数据消耗之后调用的新线程中。

拓扑中的样本处理器:

public class Processor implements Processor<K, V> {

@Override
  public void process(String key, V value) {

  //Spawn new thread to do the processing
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(() -> {
      String threadName = Thread.currentThread().getName();
      System.out.println("Hello " + threadName);

      //Do more processing
      ...

      // Write back to output topic
      context.forward(key, updatedValue)
    }); 
  }
}

我已经尝试过最基本的代码,但是不能确定它是否干扰了Kafka提供的自动功能。例如自动提交偏移量,超时等。

还是坚持使用Kafka流已提供的默认行为并利用流线程快速处理数据总是更好的方法?

2 个答案:

答案 0 :(得分:0)

Kafka流使用kafka使用者API来消耗来​​自kafka主题的消息。这意味着即使生成多个线程来使用消息,多余的线程也将保持空闲状态。

例如,如果您的主题有5个分区,即使您产生10个线程从该主题中读取内容,kafka消费者api也将仅使用5个线程从该主题中读取内容,其余线程将处于空闲状态。

您可以在定义流配置时定义要产生的线程数。

Properties streamsConfig = new Properties();

streamsConfig.put(StreamsConfig.NUM_STREAM_THREADS_CONFIG, 1); //Here number of threads being spawned per kafka streams app node is 1 

因此,如果您的主题有10个分区,并且kafka stream应用程序部署在两个节点上,则NUM_STREAM_THREADS_CONFIG为5。

让我知道您是否需要更多帮助!

答案 1 :(得分:0)

不建议您启动自己的线程,因为这会破坏Kafka Streams的容错保证。如果process()返回,则Kafka Streams假定已完全处理了一条消息,并且所有可能的输出消息都是通过forward()发送的。对于这种情况,Kafka Streams可能会提交输入记录偏移。

但是,如果您在后台线程中处理消息,并且该线程处理失败,则Kafka Streams将一无所知,因此即使发生故障并且消息将丢失,偏移也会被提交。 / p>

此外,返回forward()后不允许后台线程调用process()。如果forward()被称为process()的“外部”,则Kafka Streams将引发异常。

但是,如果不是不可能使用自己的后台线程并保留至少一次处理保证,则它相当复杂,因此不建议使用。