【问题标题】:AWS Kinesis Client Java: Setting up TRIM_HORIZON Position in Stream does not workAWS Kinesis Client Java:在 Stream 中设置 TRIM_HORIZON 位置不起作用
【发布时间】:2021-07-26 17:38:44
【问题描述】:

我正在运行一个测试系统,该系统生成一个 Kinesis 生产者,该生产者开始写入消息,例如:1 到 100 到具有两个分片的流。

在该循环期间,消费者开始从流中读取消息。我注意到消费者只读取运行后进入流的LATEST 消息。例如,它从第 43 条消息开始读取。我尝试修改 Worker.class 以使用 TRIM_HORIZON 策略,但这似乎不起作用。

KinesisClientLibConfiguration c = new KinesisClientLibConfiguration("MediaPlan", "randeepstream",
    DefaultAWSCredentialsProviderChain.getInstance(),
    "consumer1")
    .withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON);
final Worker w = new Worker.Builder()
    .recordProcessorFactory(rpf)
    .config(kinesisConfig)
    .build();
new Thread(() -> w.run()).start();

我的消费者的处理器设置为:

public class ConsumerRecordProcessorImpl implements IRecordProcessor {

    public void initialize(InitializationInput initializationInput) {
        log.info("Setting up consumer with shard {} starting at {}", initializationInput.getShardId(),
                initializationInput.getExtendedSequenceNumber());
    }

    public void processRecords(ProcessRecordsInput processRecordsInput) {
        ...
    }
}

我希望看到如下消息: Setting up consumer with shard shardId-000000000000 starting at TRIM_HORIZON 0 但相反,我得到: Setting up consumer with shard shardId-000000000000 starting at LATEST 0

如何让我的消费者停止阅读最新消息并阅读所有未处理的消息?

【问题讨论】:

    标签: java amazon-kinesis amazon-kinesis-client


    【解决方案1】:

    这是一个使用 amazon-kinesis-client lib v2 的示例。

    您将不得不使用 Schedular(software.amazon.kinesis.coordinator) 在后台读取记录并向此调度程序提供检索配置,如下所示

    RetrievalConfig retrievalConfig = setRetrievalConfig();
    
    Scheduler scheduler = new Scheduler(
            configsBuilder.checkpointConfig(),
            configsBuilder.coordinatorConfig(),
            configsBuilder.leaseManagementConfig(),
            configsBuilder.lifecycleConfig(),
            configsBuilder.metricsConfig(),
            configsBuilder.processorConfig(),
            retrievalConfig);
    
    private RetrievalConfig setRetrievalConfig(){
        InitialPositionInStreamExtended initialPositionInStreamExtended = InitialPositionInStreamExtended.newInitialPosition(InitialPositionInStream.TRIM_HORIZON);
        RetrievalConfig retrievalConfig = configsBuilder.retrievalConfig().retrievalSpecificConfig(new PollingConfig(streamName, kinesisClient));
        retrievalConfig.initialPositionInStreamExtended(initialPositionInStreamExtended);
        return retrievalConfig;
    }
    

    注意InitialPositionInStream.TRIM_HORIZON 这将告诉调度程序在最后一个已知位置之后开始使用记录。所以即使消费者宕机,生产者还在运行,消费者宕机期间产生的所有记录都会被消费掉。

    注意:configBuilder 是 ConfigsBuilder (software.amazon.kinesis.common) 的对象

    更新:initialPositionInStream 位置不会更新,除非您在处理从 kinesis 收到的数据后调用 checkpoint() API。 因此,一旦您调用 checkpinter(),流处理记录的最新位置就会在 DynamoDB 中更新,现在 KCL 将从该位置处理记录。

    【讨论】:

    • 重要提示:该设置 (InitialPositionInStream.TRIM_HORIZON) 仅在第一个应用程序启动之前有效。一开始,它存储在 DynamoDB 表中,之后总是从 DynamoDB 中读取,完全忽略了代码中的设置。要解决这个问题,要么删除 DynamoDB 表(它将使用代码中的设置再次创建)要么将字段 checkpoint 的值更新为 TRIM_HORIZON
    • 它不是第一次启动应用程序,而是每次重新启动。每次重新启动的 TRIM (InitialPositionInStream.TRIM_HORIZON) 流压将从最后一个位置继续。如果应用程序关闭了一段时间,则下一个处理将从应用程序重新启动时的最后一个检查点开始。成功处理收到的运动记录后,您必须执行检查点调用。 aws 文档中也提到了这一点:amzn.to/2VbVTr3TRIM_HORIZON:从分片中最后一个未修剪的记录开始流式传输,这是分片中最旧的数据记录。对于检查指针调用,请参阅 KCL
    • 你错过了一个想法。设置 InitialPositionInStream 实际上存储在您选择保存租约所有者信息的 DynamoDB 表中。如果您的应用程序启动时表存在。 InitialPositionInStream 设置未更新!我花了将近一个小时来理解这一点。我尝试在代码中将设置从 LATEST 更改为 TRIM_HORIZONT,直到我在表格中更改它后应用程序才更改它
    • 你是绝对正确的@AlexeySviridov InitialPositionInStream 实际上存储在 DynamoDB 中。 InitialPositionInStream 位置不会更新,除非您在处理从 kinesis 收到的数据后调用 checkpoint() API。因此,一旦您调用 checkpinter(),流处理记录的最新位置就会在 DynamoDB 中更新,现在 KCL 将从该位置处理记录。因此,即使您的应用程序已关闭,您也不会错过 Stream 中的数据并继续从存储在 DynmoDB 中的最后一个检查点开始处理。我想没有错过重点:)
    • 是的,你现在完全正确。最后一条评论使事情变得完全清晰和正确。那么,也许这是更新答案的好理由? :)
    猜你喜欢
    • 2018-11-20
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2021-02-15
    • 2017-12-16
    相关资源
    最近更新 更多