Apache Kafka - 有可能丢失错误消息吗?

时间:2017-10-12 09:00:48

标签: java apache-kafka spring-cloud-stream

我用Apache Kafka挖掘Spring Cloud Stream并观察了一些行为让我想知道我做错了什么或是否按预期工作 - 我几乎不怀疑:

错误消息可能会丢失!?

我的设置尽可能简单。单个Kafka代理和仅包含1个分区的主题。具有默认设置的经纪人,主题,生产者和消费者(auto-ack为真)。

testcase 1

  • 制作message2
  • 制作message1
  • 启动一个消费者,在接收任何消息
  • 时会抛出RuntimeException
  • 消费message1,重试
  • 消费message1,重试
  • 消费message2,重试
  • 抛出异常
  • 消费message2,重试
  • 消费message2,重试
  • 消费message1,重试
  • 抛出异常
  • 停止并重新启动消费者
  • 消费message1,重试
  • 消费message1,重试
  • 消费message2,重试
  • 抛出异常
  • 消费message2,重试
  • 消费message2,重试
  • 消费message1,重试
  • 抛出异常

按预期工作。

testcase 2

  • 制作message2
  • 制作message1
  • 启动一个消费者,在接收完全message1
  • 时会抛出RuntimeException
  • 消费message1,重试
  • 消费message1,重试
  • 消费message2,重试
  • 抛出异常
  • 成功使用message3
  • 制作message3
  • 成功使用message1
  • 停止并重新启动消费者
  • 没有任何反应,消费者等待新消息消费
将跳过

message3,因为已提交的偏移量已设置为kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test-topic 。这让我很烦恼。只要先前的消息未成功处理,我就不希望消费者继续留言。

有没有人遇到过同样的行为和/或可能会指导我如何改变这种行为?

提前致谢!

更新:根据要求提供了一些代码段

创建主题

kafka-console-producer.sh --broker-list localhost:9092 --topic test-topic

连接制片人

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.7.RELEASE</version>
    <relativePath/>
</parent>

...

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>


<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-kafka</artifactId>
    </dependency>
</dependencies>

使用

创建maven项目
application.yml

添加以下spring: cloud: stream: bindings: input: destination: test-topic contentType: text/plain group: test-group consumer: header-mode: raw kafka: binder: zkNodes: localhost:2181 brokers: localhost:9092

Application.java

添加以下@SpringBootApplication @EnableBinding(Sink.class) public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); } @StreamListener(Sink.INPUT) private void consume(Message<String> message) { log.info("Received: {}", message.getPayload()); if ("message1".equals(message.getPayload()) throw new RuntimeException(); log.info("Successfully processed message {}", message.getPayload()); } }

GregorianCalendar today = new GregorianCalendar ();

那应该是它。运行应用程序并使用console-producer生成消息。

3 个答案:

答案 0 :(得分:0)

Kafka为您提供运行时,但您有选择的权力。在某些情况下,msgs可能会丢失/跳过,有些可能不会 - 您需要根据需要准备配置。 IMO你应该进一步调查一些Spring Cloud Stream设置。您也可以使用禁用自动提交和提交偏移量#34;手动&#34;。

答案 1 :(得分:0)

在Kafka中,每封邮件都附带一个偏移ID。您的消费者应用程序可以检查偏移量,以及是否跳过或错过任何偏移量而不是消耗下一条消息。您可以使用 consumer.seek 方法获取缺少的特定消息。

偏移本质上是递增的,也是连续的。

在您的情况下使用手动提交。

我可以说使用以下步骤..

  1. 在poll方法之后,首先检查先前提交的偏移量和 并请求下一个偏移值

  2. 消息成功使用并处理后,请保存     某些内部成功处理的消息的偏移值     记忆或表格。在下次调查期间

  3. 以下链接不会用作您的用例,但您可以获得公平的想法

    参考Example

答案 2 :(得分:0)

您应该为这种情况配置DLQ。如果您的消息在3次重试后无法消费,则很可能根本不会消费或者需要特殊处理。 设置有毒消息可能落地的DLQ,并且您不会丢失消息