我正在尝试在AWS服务之上构建数据收集管道。下面给出了总体架构;
总之,系统应该从API网关(1)获取事件(每个事件一个请求),并且应该将数据写入Kinesis(2)。
我期待每秒约100k个事件。我的问题与Lambda函数的KPL使用有关。在第2步,我计划用KPL编写一个Lambda方法,以高吞吐量在Kinesis上编写事件。但我不确定它是否可能,因为API网关分别为每个事件调用lambda函数。
在这种架构中使用KPL是否可能/合理,或者我应该使用Kinesis Put API?
1 2 3 4
+----------------+ +----------------+ +----------------+ +----------------+
| | | | | | | |
| | | | | | | |
| AWS API GW +-----------> | AWS Lambda +-----------> | AWS Kinesis +----------> | AWS Lambda |
| | | Function with | | Streams | | |
| | | KPL | | | | |
| | | | | | | |
+----------------+ +----------------+ +----------------+ +-----+-----+----+
| |
| |
| |
| |
| |
5 | | 6
+----------------+ | | +----------------+
| | | | | |
| | | | | |
| AWS S3 <-------+ +----> | AWS Redshift |
| | | |
| | | |
| | | |
+----------------+ +----------------+
我也在考虑直接写S3而不是从api-gw调用lambda函数。如果第一个架构不合理,这可能是一个解决方案,但在这种情况下,我会有延迟,直到将数据写入kinesis
1 2 3 4 5
+----------------+ +----------------+ +----------------+ +----------------+ +----------------+
| | | | | | | | | |
| | | | | | | | | |
| AWS API GW +-----------> | AWS Lambda +------> | AWS Lambda +-----------> | AWS Kinesis +----------> | AWS Lambda |
| | | to write data | | Function with | | Streams | | |
| | | to S3 | | KPL | | | | |
| | | | | | | | | |
+----------------+ +----------------+ +----------------+ +----------------+ +-----+-----+----+
| |
| |
| |
| |
| |
6 | | 7
+----------------+ | | +----------------+
| | | | | |
| | | | | |
答案 0 :(得分:2)
我不认为使用KPL是正确的选择。 KPL的关键概念是,在客户端收集记录,然后作为批处理操作发送给Kinesis。由于Lambdas每次调用都是无状态的,因此存储聚合记录(在将其发送到Kinesis之前)相当困难。
我认为您应该查看以下AWS文章,该文章解释了如何将API-Gateway直接连接到Kinesis。这样,您就可以避免额外的Lambda,它只是转发您的请求。
答案 1 :(得分:0)
很显然,如果您通过AWS API Gateway传递的数据与一个Kinesis Data Streams记录相对应,那么Jens指出使用KPL是没有意义的。在这种情况下,您可以直接调用Kinesis API,而无需使用Lambda。最终,您可能会在Lambda中使用一些其他处理,并通过PutRecord(而不是KPL使用的PutRecords)发送数据。您在JAVA中的代码将如下所示:
AmazonKinesisClientBuilder clientBuilder = AmazonKinesisClientBuilder.standard();
clientBuilder.setRegion(REGION);
clientBuilder.setCredentials(new DefaultAWSCredentialsProviderChain());
clientBuilder.setClientConfiguration(new ClientConfiguration());
AmazonKinesis kinesisClient = clientBuilder.build();
...
//then later on each record
PutRecordRequest putRecordRequest = new PutRecordRequest();
putRecordRequest.setStreamName(STREAM_NAME);
putRecordRequest.setData(data);
putRecordRequest.setPartitionKey(daasEvent.getAnonymizedId());
putRecordRequest.setExplicitHashKey(Utils.randomExplicitHashKey());
putRecordRequest.setSequenceNumberForOrdering(sequenceNumberOfPreviousRecord);
PutRecordResult putRecordResult = kinesisClient.putRecord(putRecordRequest);
sequenceNumberOfPreviousRecord = putRecordResult.getSequenceNumber();
但是,在某些情况下,使用lambda的KPL是有意义的。例如,发送到AWS API Gateway的数据包含多个单独的记录,这些记录将发送到一个或多个流。在那种情况下,KPL的好处(参见https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-concepts.html)仍然有效,但是您必须了解使用Lambda所给出的具体细节,此处https://github.com/awslabs/amazon-kinesis-producer/issues/143指出并使用
kinesisProducer.flushSync()
在插入结束时也对我有用。