简体   繁体   English

消费者的 Amazon Kinesis KCL 客户端在 .NET 中不工作

[英]Amazon Kinesis KCL client for Consumer not working in .NET

please help.请帮忙。 I am having problems setting up the Consumer for Kinesis data stream in .NET console application.我在 .NET 控制台应用程序中为 Kinesis 数据 stream 设置消费者时遇到问题。

I have done everything according to the documentation, but I still get a blank console screen whenever I run the consumer.我已经根据文档完成了所有操作,但是每当我运行消费者时,我仍然会得到一个空白的控制台屏幕。 The producer works fine so far and the AWS credentials are working.到目前为止,生产者工作正常,AWS 凭证正在工作。

  1. I have JDK on my system all well configured (not new to Java development)我的系统上的 JDK 配置良好(对于 Java 开发来说不是新手)
  2. I have all the necessary policies attached to my IAM user我已将所有必要的策略附加到我的 IAM 用户
  3. I can see that the producer can programmatically create streams, desc streams etc with the same AWS credentials我可以看到生产者可以使用相同的 AWS 凭证以编程方式创建流、描述流等

I can hit the breakpoint in Program when creating the KclProcess but I cannot hit any breakpoint inside the KinesisTest class below创建 KclProcess 时,我可以在 Program 中打断点,但我无法在下面的 KinesisTest class 中打任何断点

As for the consumer, I've created a class Program.cs like below:至于消费者,我创建了一个 class Program.cs,如下所示:

class Program  
{

    public static void Main(string[] args)
    {
        //added these lines after trying everything
        Environment.SetEnvironmentVariable("AWS_ACCESS_KEY_ID", "***");
        Environment.SetEnvironmentVariable("AWS_SECRET_ACCESS_KEY", "***");
        Environment.SetEnvironmentVariable("AWS_REGION", "us-east-1");

        try
        {
            KclProcess.Create(new KinesisTest()).Run();
        }
        catch (Exception e)
        {
            Console.Error.WriteLine("ERROR: " + e);
        }
    }

}

and another class和另一个 class

public class KinesisTest: IRecordProcessor
{

    private static readonly TimeSpan Backoff = TimeSpan.FromSeconds(3);
    private static readonly TimeSpan CheckpointInterval = TimeSpan.FromMinutes(1);
    private static readonly int NumRetries = 10;

    /// <value>The shard ID on which this record processor is working.</value>
    private string _kinesisShardId;

    private DateTime _nextCheckpointTime = DateTime.UtcNow;


    public void Initialize(InitializationInput input)
    {
        Console.Error.WriteLine("Initializing record processor for shard: " + input.ShardId);
        this._kinesisShardId = input.ShardId;
    }

    public void ProcessRecords(ProcessRecordsInput input)
    {
        Console.Error.WriteLine("Processing " + input.Records.Count + " records from " + _kinesisShardId);
        ProcessRecordsWithRetries(input.Records);

        // Checkpoint once every checkpoint interval.
        if (DateTime.UtcNow >= _nextCheckpointTime)
        {
            Checkpoint(input.Checkpointer);
            _nextCheckpointTime = DateTime.UtcNow + CheckpointInterval;
        }
    }

    public void Shutdown(ShutdownInput input)
    {
        Console.Error.WriteLine("Shutting down record processor for shard: " + _kinesisShardId);
        // Checkpoint after reaching end of shard, so we can start processing data from child shards.
        if (input.Reason == ShutdownReason.TERMINATE)
        {
            Checkpoint(input.Checkpointer);
        }
    }

    private void ProcessRecordsWithRetries(List<Record> records)
    {
        foreach (Record rec in records)
        {
            bool processedSuccessfully = false;
            string data = null;
            for (int i = 0; i < NumRetries; ++i)
            {
                try
                {
                    data = System.Text.Encoding.UTF8.GetString(rec.Data);

                    Console.Error.WriteLine( String.Format("Retrieved record:\n\tpartition key = {0},\n\tsequence number = {1},\n\tdata = {2}", rec.PartitionKey, rec.SequenceNumber, data));

                    // Your own logic to process a record goes here.

                    processedSuccessfully = true;
                    break;
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine("Exception processing record data: " + data, e);
                }

                //Back off before retrying upon an exception.
                Thread.Sleep(Backoff);
            }

            if (!processedSuccessfully)
            {
                Console.Error.WriteLine("Couldn't process record " + rec + ". Skipping the record.");
            }
        }
    }

    private void Checkpoint(Checkpointer checkpointer)
    {
        Console.Error.WriteLine("Checkpointing shard " + _kinesisShardId);

        checkpointer.Checkpoint(RetryingCheckpointErrorHandler.Create(NumRetries, Backoff));
    }
}

and lastly the kcl.properties file:最后是 kcl.properties 文件:

executableName = dotnet KinesisTest.dll

streamName = testStream

applicationName = KinesisTest

AWSCredentialsProvider = DefaultAWSCredentialsProviderChain

processingLanguage = C#

initialPositionInStream = TRIM_HORIZON

regionName = us-east-1

maxRecords = 5000

idleTimeBetweenReadsInMillis = 1000

# failoverTimeMillis = 10000
# workerId =
# shardSyncIntervalMillis = 60000
# callProcessRecordsEvenForEmptyRecordList = false
# parentShardPollIntervalMillis = 10000
# cleanupLeasesUponShardCompletion = true
# taskBackoffTimeMillis = 500
# metricsBufferTimeMillis = 10000
# metricsMaxQueueSize = 10000
# validateSequenceNumberBeforeCheckpointing = true
# maxActiveThreads = 0

Please let me know if I'm doing something wrong.如果我做错了什么,请告诉我。

I was expecting to see the Consumer processing the data from the stream but it's just an empty console我期待看到消费者处理来自 stream 的数据,但它只是一个空控制台

While I never found an answer to this question, I found a better and proper way to do this using lambdas. 尽管我从未找到这个问题的答案,但我找到了一种使用lambda的更好且正确的方法。

My final setup involved using SNS to get the messages/events from Kinesis and then fanning out the message to any subscribers (In my case, SQS queues) which then provide the queued messages to lambdas. 我的最终设置包括使用SNS从Kinesis获取消息/事件,然后将消息散发给任何订阅者(在我的情况下为SQS队列),然后将排队的消息提供给lambda。

Something like this: 像这样:

                             SQS Queue ----------------> Lambda
                             ^
                            /
                           /
                          /
KINESIS STREAM ------->SNS-------->SQS Queue ------> Lambda
                          \
                           \
                            \
                             >SQS Queue ----------------> Lambda

You might ask why not Kinesis to SQS directly? 您可能会问为什么不直接将Kinesis转换为SQS? or why not SNS to Lambda directly? 还是为什么不将SNS直接发送给Lambda?

First question's answer is that Kinesis isn't build for multiple reads. 第一个问题的答案是,Kinesis并非针对多次读取而构建。 SNS allows you to read once and fan it out to as many subscribers as you need. SNS允许您阅读一次并根据需要将其分发给尽可能多的订户。 If you have say 20 listeners who are waiting to act on an event, you can't plug them all into Kinesis. 如果说有20位等待事件发生的听众,则不能将他们全部插入Kinesis。 So go SNS. 所以去SNS吧。

Second question's answer is that SNS sometimes can lose messages and not deliver or trigger the lambdas (very true). 第二个问题的答案是,SNS有时可能会丢失消息,并且无法传递或触发lambda(非常正确)。 However (speculated based on experience) this probability reduces if you connect it to SQS, it almost always lands in the queue. 但是(根据经验推测),如果将其连接到SQS,则这种可能性会降低,它几乎总是落在队列中。 The queues can then trigger the lambdas.. They have only one job anyway. 然后,队列可以触发lambda。无论如何,它们只有一项工作。

So I hope this helps someone. 所以我希望这对某人有帮助。

You have to run this by Bootstrap project.您必须通过 Bootstrap 项目运行它。 Bootstrap project run Java program which run your project.引导项目运行 Java 程序来运行您的项目。 You can find ready Bootstrap project in KCL for .NET repo.您可以在 KCL 中为 .NET 存储库找到现成的 Bootstrap 项目。

https://github.com/awslabs/amazon-kinesis-client-net/tree/master/Bootstrap https://github.com/awslabs/amazon-kinesis-client-net/tree/master/Bootstrap

Perhaps you will have to do some changes in this project like a set "pom.xml" location or something else but you can debug this project to find out if everything started correctly.也许您将不得不在此项目中进行一些更改,例如设置“pom.xml”位置或其他内容,但您可以调试此项目以了解一切是否正确启动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM