并发MessageListenerContainer分配主题分区

时间:2019-03-27 10:13:41

标签: spring-kafka

我正在设置ConcurrentMessageListenerContainer

<bean class="org.springframework.kafka.listener.ConcurrentMessageListenerContainer" id="messageListenerContainer">
        <constructor-arg index="0" ref="consumerFactory"/>
        <constructor-arg index="1" ref="containerProperties"/>
        <property name="concurrency" value="2"/>
    </bean>

ConsumerFactory使用此配置:

    <util:map id="consumerConfig" map-class="java.util.HashMap">
        <entry key="#{T(org.apache.kafka.clients.consumer.ConsumerConfig).BOOTSTRAP_SERVERS_CONFIG}"
               value="${rp.kafka.bootstrap.servers}"/>
        <entry key="#{T(org.apache.kafka.clients.consumer.ConsumerConfig).KEY_DESERIALIZER_CLASS_CONFIG}"
               value="org.apache.kafka.common.serialization.StringDeserializer"/>
        <entry key="#{T(org.apache.kafka.clients.consumer.ConsumerConfig).VALUE_DESERIALIZER_CLASS_CONFIG}"
               value="org.springframework.kafka.support.serializer.JsonDeserializer"/>
        <entry key="#{T(org.springframework.kafka.support.serializer.JsonDeserializer).TRUSTED_PACKAGES}"
               value="*"/>
        <entry key="#{T(org.apache.kafka.clients.consumer.ConsumerConfig).PARTITION_ASSIGNMENT_STRATEGY_CONFIG}"
               value="org.apache.kafka.clients.consumer.RoundRobinAssignor"/>
        <entry key="#{T(org.apache.kafka.clients.consumer.ConsumerConfig).ENABLE_AUTO_COMMIT_CONFIG}"
               value="false"/>
    </util:map>

和ContainerProperty是

    <bean class="org.springframework.kafka.listener.ContainerProperties" id="containerProperties">
        <constructor-arg>
            <list>
                <value>sendSMS</value>
            </list>
        </constructor-arg>
        <property name="groupId" value="main"/>
        <property name="messageListener" ref="messageListener"/>
        <property name="ackMode" value="RECORD"/>
    </bean>

我的主题“ sendSMS”在3节点群集上有5个分区,表示因子为3,因此我希望由并发创建的每个KafkaMessageListenerContainer(在这种情况下共2个)将占用一部分分区。但是,在启动应用程序后,我在调试器窗口中看到每个侦听器都在处理所有5个侦听器!隔断 https://gyazo.com/183626ff60061b471858f8cc52573353 和来自第4个分区的消息(在该消息中,我有一个挂起处理的消息,并且在重启后未提交,但与该问题无关),在相同偏移量上的第4个分区在具有不同使用者的不同线程中传递了2次!为什么会这样呢?是错误还是预期的行为?

1 个答案:

答案 0 :(得分:0)

您没有显示足够的信息。并发容器聚合子KafkaListenerContainer的分配分区(每个并发分配一个)。

@Override
public Collection<TopicPartition> getAssignedPartitions() {
    return this.containers.stream()
            .map(KafkaMessageListenerContainer::getAssignedPartitions)
            .filter(Objects::nonNull)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
}

您需要显示重新交付的日志;打开调试日志记录以获取更多信息。