Spring boot 如何逐一使用卡夫卡主题中的消息

Spring boot 如何逐一使用卡夫卡主题中的消息,spring-boot,apache-kafka,spring-cloud,spring-cloud-stream,Spring Boot,Apache Kafka,Spring Cloud,Spring Cloud Stream,我用一个分区构建了一个卡夫卡主题 kafka-topics --create --topic files.write --if-not-exists --zookeeper zookeeper:32181 --partitions 1 --replication-factor 1 在这个主题中可以推送许多消息 但我希望给定组的单个消费者逐个处理这些消息 spring: application: name: file-consumer cloud: stream:

我用一个分区构建了一个卡夫卡主题

kafka-topics --create --topic files.write --if-not-exists --zookeeper zookeeper:32181 --partitions 1 --replication-factor 1
在这个主题中可以推送许多消息

但我希望给定组的单个消费者逐个处理这些消息

spring:
  application:
    name: file-consumer
  cloud:
    stream:
      kafka:
        binder:
          type: kafka
          brokers: localhost
          defaultBrokerPort: 29092
          defaultZkPort: 32181
          configuration:
            max.request.size: 300000
            max.message.bytes: 300000
        bindings:
          fileWriteBindingInput:
            consumer:
              autoCommitOffset: false
      bindings:
        fileWriteBindingInput:
          binder: kafka
          destination: files.write
          group: ${spring.application.name}
          contentType: 'text/plain'
以及Java示例代码

@StreamListener(FileBindingProcessor.INPUT_FILE_WRITE)
public void onInputMessage(Message<String> message, @Header(KafkaHeaders.ACKNOWLEDGMENT) Acknowledgment acknowledgment) {

    // I Would like here to synchronize the processing of messages one by one
    // But, If many messages are pushed to this topic (single partition), they will be processed asynchronously event if I didn't yet acknowledge the current message

    acknowledgment.acknowledge();
}
我的配置中缺少什么

我想,虽然消息未确认偏移量没有增加,但同一分区中没有其他消息被使用。

如果启用了默认的autoCommitOffset,那么绑定器将已经确认每个记录。因此,当它到达您的StreamListener时,记录已经被确认

kafka-topics --create --topic files.write --if-not-exists --zookeeper zookeeper:32181 --partitions 1 --replication-factor 1
更正:上面关于StreamListener的说法不太正确。自动确认在侦听器退出时完成

由于您只有一个分区,因此您将按照发送到该主题分区的相同顺序获取消息。 您可以禁用autoCommitOffset,在这种情况下,您可以使用手动确认

如果启用了默认的自动提交设置,则活页夹将已经确认每条记录。因此,当它到达您的StreamListener时,记录已经被确认

更正:上面关于StreamListener的说法不太正确。自动确认在侦听器退出时完成

由于您只有一个分区,因此您将按照发送到该主题分区的相同顺序获取消息。
您可以禁用autoCommitOffset,在这种情况下,您可以使用手动确认

您可以将此consumer config max.poll.records设置为1,默认值为500

最大投票记录

在单个轮询调用中返回的最大记录数


您可以将此消费者配置max.poll.records设置为1,默认值为500

最大投票记录

在单个轮询调用中返回的最大记录数


不确认消息与停止下一条消息的传递无关


您不能将消息传递给另一个线程并在以后确认它;如果需要单线程处理,则必须在侦听器线程上执行所有处理。

不确认消息与停止下一条消息的传递无关


您不能将消息传递给另一个线程并在以后确认它;如果需要单线程处理,则必须在侦听器线程上完成所有处理。

谢谢。但事实上我已经这么做了。我已禁用自动提交设置。我想在确认未完成时不会再消耗消息。哦,好的。我没有注意到在您的配置中。>因此,当它到达您的StreamListener时,记录已经被确认。-不完全正确;“自动确认”是在侦听器退出时完成的,与问题无关,但我想澄清一下。谢谢,@GaryRussell。更新了答案。谢谢。但事实上我已经这么做了。我已禁用自动提交设置。我想在确认未完成时不会再消耗消息。哦,好的。我没有注意到在您的配置中。>因此,当它到达您的StreamListener时,记录已经被确认。-不完全正确;“自动确认”是在侦听器退出时完成的,与问题无关,但我想澄清一下。谢谢,@GaryRussell。更新了答案。此链接可能对您有帮助:此链接可能对您有帮助:谢谢。但我没有看到任何结果。也许配置不好。我在这里设置了max.pool.records:spring.cloud.stream.kafka.binder.bindings.filewritebindingingput.consumer.configuration.max.poll.records:1我看不到任何结果您的意思是什么?这不管用吗?你有超过1张的记录吗@奥利维耶特瑞恩是的。我仍然同时使用许多消息。但可能我的配置不好。请删除max.request.size和max.message.bytes,我会尝试使用它,并参考@gray russell answer,再次感谢。我会继续探索这条路。谢谢。但我没有看到任何结果。也许配置不好。我在这里设置了max.pool.records:spring.cloud.stream.kafka.binder.bindings.filewritebindingingput.consumer.configuration.max.poll.records:1我看不到任何结果您的意思是什么?这不管用吗?你有超过1张的记录吗@奥利维耶特瑞恩是的。我仍然同时使用许多消息。但可能我的配置不好。请删除max.request.size和max.message.bytes,我会尝试使用它,并参考@gray russell answer,再次感谢。我会继续探索这条路。嗨,加里。也许ack方法不是好的解决方案。即使将max.poll.records配置为逐个消费消息,我也可以在日志中看到消息同时被消费。例如,我将4条消息推送到一个partioned主题,并由一个消费者使用它们。我可以在日志中看到所有的消息都被消耗了,即使第一条消息没有被确认。我的需要
仅当处理第一条消息时才处理第二条消息。这就是为什么我认为ack是解决方案。不清楚你的意思。从容器的角度来看,handled意味着监听器方法退出。确认只需在代理上提交偏移量,这意味着如果重新启动应用程序,您将不会再次收到该消息。如果您将消息交给另一个线程进行处理,则无论使用者属性如何,您都将获得下一条消息。要执行所需操作,必须在退出侦听器方法之前完成所有处理。抱歉。Handle、consumer、processe、get对于并发性为1的meIt来说都是相同的。我想我的主要问题是我的被动使用造成的。我用subscribe代替block。我在这里发布了我的示例:。顺便说一下,谢谢你的帮助嗨,加里。也许ack方法不是好的解决方案。即使将max.poll.records配置为逐个消费消息,我也可以在日志中看到消息同时被消费。例如,我将4条消息推送到一个partioned主题,并由一个消费者使用它们。我可以在日志中看到所有消息都被消耗,即使第一条消息没有被确认。我的需要是只在第一条消息被处理时处理第二条消息。这就是为什么我认为ack是解决方案。不清楚你的意思。从容器的角度来看,handled意味着监听器方法退出。确认只需在代理上提交偏移量,这意味着如果重新启动应用程序,您将不会再次收到该消息。如果您将消息交给另一个线程进行处理,则无论使用者属性如何,您都将获得下一条消息。要执行所需操作,必须在退出侦听器方法之前完成所有处理。抱歉。Handle、consumer、processe、get对于并发性为1的meIt来说都是相同的。我想我的主要问题是我的被动使用造成的。我用subscribe代替block。我在这里发布了我的示例:。顺便说一下,谢谢你的帮助