簡體   English   中英

spring integration kafka listener線程在concurrency = partition count時讀取多個partition

[英]spring integration kafka listener thread reads multiple partitions when concurrency = partition count

我設置了一個 Spring Integration 流來處理具有 3 個分區的主題,並將偵聽器容器的並發設置為 3。正如預期的那樣,我看到三個線程處理來自所有 3 個分區的批處理。 但是,我看到在某些情況下,其中一個偵聽器線程可能會處理包含來自多個分區的消息的單個批處理。 我的數據在 kafka 中由一個 id 進行分區,以便它可以與其他 id 同時處理,但不能在另一個線程上使用相同的 id(這是我驚訝地發現正在發生的事情)。 我從閱讀文檔中認為每個線程都會被分配一個分區。 我正在使用這樣的 KafkaMessageDrivenChannelAdapter:

private static final Class<List<MyEvent>> payloadClass = (Class<List<MyEvent>>)(Class) List.class;

public KafkaMessageDrivenChannelAdapterSpec.KafkaMessageDrivenChannelAdapterListenerContainerSpec<String, MyEvent> myChannelAdapterSpec() {
        return Kafka.messageDrivenChannelAdapter(tstatEventConsumerFactory(),
                KafkaMessageDrivenChannelAdapter.ListenerMode.batch, "my-topic") //3 partitions
                .configureListenerContainer(c -> {
                    c.ackMode(ContainerProperties.AckMode.BATCH);
                    c.id(_ID);
                    c.concurrency(3);
                    RecoveringBatchErrorHandler errorHandler = new RecoveringBatchErrorHandler(
                            (record, exception) -> log.error("failed to handle record at offset {}: {}",
                                    record.offset(), record.value(), exception),
                            new FixedBackOff(FixedBackOff.DEFAULT_INTERVAL, 2)
                    );
                    c.errorHandler(errorHandler);
                });
    }
@Bean
public IntegrationFlow myIntegrationFlow() {
        return IntegrationFlows.from(myChannelAdapterSpec())
                .handle(payloadClass, (payload, headers) -> {
                    service.performSink(payload);
                    return null;
                })
                .get();
    }

我該如何設置,以便每個偵聽器容器線程只處理來自一個分區的消息?

但是,即使確實發生了重新平衡,是否還有一種方法可以防止我收到來自多個分區的消息的批處理?

這不是消費者群體的工作方式。 如果您想擁有“粘性”消費者,請考慮使用手動分配。 查看基於TopicPartitionOffset... topicPartitions的通道適配器工廠:

/**
 * Create an initial
 * {@link KafkaMessageDrivenChannelAdapterSpec.KafkaMessageDrivenChannelAdapterListenerContainerSpec}.
 * @param consumerFactory the {@link ConsumerFactory}.
 * @param listenerMode the {@link KafkaMessageDrivenChannelAdapter.ListenerMode}.
 * @param topicPartitions the {@link TopicPartitionOffset} vararg.
 * @param <K> the Kafka message key type.
 * @param <V> the Kafka message value type.
 * @return the KafkaMessageDrivenChannelAdapterSpec.KafkaMessageDrivenChannelAdapterListenerContainerSpec.
 */
public static <K, V>
KafkaMessageDrivenChannelAdapterSpec.KafkaMessageDrivenChannelAdapterListenerContainerSpec<K, V> messageDrivenChannelAdapter(
        ConsumerFactory<K, V> consumerFactory,
        KafkaMessageDrivenChannelAdapter.ListenerMode listenerMode,
        TopicPartitionOffset... topicPartitions) {

然后它不會被視為消費者組,您必須創建多個通道適配器,將每個通道適配器指向其特定分區。 所有這些通道適配器都可以向同一個MessageChannel發出消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM