以下是我正在尝试的简化方案:
http请求 - > (Gateway API + lambda A) - > SQS - > (lambda B. ?????) - > DynamoDB
所以它应该如图所示:来自许多http请求的数据(例如,每秒高达500) 由我的lambda函数A放入SQS队列。然后另一个函数B处理队列: 最多可读取10个项目(在某些期刊基础上),并使用BatchWriteItem将它们写入DynamoDB。
问题在于我无法弄清楚如何触发第二个lambda函数。它应该被频繁调用,每秒多次(或至少每秒一次),因为我需要队列中的所有数据尽快进入DynamoDB(这就是为什么通过所描述的调度事件调用lambda函数B的原因{ {3}}不是一个选项)
为什么我不想在没有SQS的情况下直接写入DynamoDB?
对我来说,完全避免使用SQS会很棒。我试图用SQS解决的问题是DynamoDB限制。甚至没有限制自己,而是在使用AWS SDK将数据写入DynamoDB时处理它的方式:当逐个编写记录并限制它们时,AWS SDK会静默重试写入,从而导致增加来自http客户端的请求处理时间&#39 ; s观点。
所以我想暂时将数据存储在队列中,发送响应" 200 OK"回到客户端,然后通过单独的函数处理队列,
使用一个DynamoDB的BatchWriteItem调用写入多个记录(其中
返回未处理的项目,而不是在限制的情况下自动重试)。 我甚至更愿意丢失一些记录,而不是增加接收和存储在DynamoDB中的记录之间的延迟
击>
UPD:如果有人感兴趣,我已经找到了如何在限制情况下使aws-sdk跳过自动重试:有一个特殊参数here。无论如何,将按照以下建议使用Kinesis
答案 0 :(得分:88)
[这并没有直接回答你的明确问题,所以根据我的经验,它会被贬低:)但是,我会回答你试图解决的根本问题。]
我们采用大量传入请求并将其提供给AWS Lambda函数以便以节奏的方式写入DynamoDB的方式是用Amazon Kinesis流替换建议架构中的SQS。
Kinesis流可以驱动AWS Lambda函数。
Kinesis流保证为任何给定密钥排序所传递的消息(对于有序的数据库操作很有用)。
Kinesis流允许您指定可以并行运行的AWS Lambda函数(每个分区一个),这可以与您的DynamoDB写入容量协调。
Kinesis流可以在一个AWS Lambda函数调用中传递多个可用消息,从而允许进一步优化。
注意:实际上从Amazon Kinesis流中读取的AWS Lambda服务然后调用该函数,而不是直接调用AWS Lambda的Kinesis流;但有时可以更容易想象出Kinesis驾驶它。对用户的结果几乎相同。
答案 1 :(得分:20)
不幸的是,你无法直接集成SQS和Lambda。但是不要担心太多。有一个解决方案!您需要在混合中添加另一个亚马逊服务,所有问题都将得到解决。
http requests --> (Gateway API + lambda A) --> SQS + SNS --> lambda B --> DynamoDB
您可以触发第二个lambda服务的SNS通知以启动它。启动后,它可以排空队列并将所有结果写入DynamoDB。为了更好地理解Lambda的可能事件源,请查看these docs。
答案 2 :(得分:14)
自2018年6月28日起,您现在可以使用SQS本地触发AWS Lambda函数。不再需要解决方法!
答案 3 :(得分:7)
也许更具成本效益的解决方案是将所有内容保存在SQS中(实际上是这样),然后运行调度事件,该事件调用处理队列中项目的多线程Lambda函数?
这样,您的队列工作人员可以完全匹配您的限制。如果队列为空,则函数可以提前完成或在单线程中开始轮询。
对于这种情况,Kinesis听起来像是一种过度杀戮 - 例如,你不需要原始订单。另外同时运行多个Lambdas肯定比仅运行一个多线程Lambda更昂贵。
您的Lambda将全部关于I / O,对AWS服务进行外部调用,因此一个功能可能非常适合。
答案 4 :(得分:1)
这是我从SQS队列收集消息的方式:
package au.com.redbarn.aws.lambda2lambda_via_sqs;
import java.util.List;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class SQSConsumerLambda implements RequestHandler<SQSEvent, String> {
@Override
public String handleRequest(SQSEvent input, Context context) {
log.info("message received");
List<SQSMessage> records = input.getRecords();
for (SQSMessage record : records) {
log.info(record.getBody());
}
return "Ok";
}
}
将您的DynamoDB代码添加到handleRequest()
,然后完成Lambda B。
答案 5 :(得分:0)
这是我解决这个问题的方法:
HTTP request --> DynamoDb --> Stream --> Lambda Function
在此解决方案中,您必须为表设置流。流将使用您将要编写的Lambda函数进行处理。无需使用SQS或其他任何东西。
当然,这是一个简化的设计,它只适用于简单的问题。对于更复杂的场景,请使用Kinesis(如其他答案中所述)。
答案 6 :(得分:0)
我相信AWS现在提出了一种SQS可以触发lambda函数的方法。因此,我想我们可以使用SQS平滑突发数据到发电机的负载,以防您不关心消息顺序。在以下新更新中查看他们的博客:https://aws.amazon.com/blogs/aws/aws-lambda-adds-amazon-simple-queue-service-to-supported-event-sources/