我们正在使用低级处理器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流已提供的默认行为并利用流线程快速处理数据总是更好的方法?
答案 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将引发异常。
但是,如果不是不可能使用自己的后台线程并保留至少一次处理保证,则它相当复杂,因此不建议使用。