Amazon SQS 触发 AWS Lambda 及重试/DLQ

Amazon 在 2018 年 6 月份宣布可以设置用 SQS 来触发 Lambda,SQS 不再是单纯用于 ECS 服务中,或用于伸缩控制的。这儿就来亲自尝试一下用 SQS 驱动的 Lambda,以及要注意的要素。

首先使用 Java 编写 Lambda 的话,AWS 在 com.amazonaws:aws-lambda-java-events:2.20 版本开始加入了 com.amazonaws.services.lambda.runtime.events.SQSEvent 类,可是这个版本的 aws-lambda-java-events 是有所限的,因为 SQSEvent.SQSMessage 类是私有的,这就造成不能获取到 SQSEvent 中的记录数据。

//下面的操作代码无法编译,因为 SQSEvent.SQSMessage 是私有的,不可访问
SQSEvent.SQSMessage sqs = sqsEvent.getRecords().get(0); 
sqsEvent.getRecords().get(0).getBody();

Java 使用 SQS 来驱动 Lambda 的话,至少需要 com.amazonaws:aws-lambda-java-events:2.2.1 版本,从此 SQSEvent.SQSMessage 变成 public 了。该版本是于  2018 年 6 月传到 Maven 官方中央仓库的,这就是那时才能真正用来写 Java 的 SQS 触发的 Lambda.

同时此篇也是作为上文 AWS Lambda 重试与死信队列(DLQ) 的一个很重要的补充。在此也会验证 SQS 触发的 Lambda 的重试机制以及 DLQ 相关的内容。 阅读全文 >>

AWS SQS 队列的 DLQ 设置与行为

和 Lambda 类似,AWS 的  SQS 队列也提供了 DLQ(Dead Letter Queue) 来支持重试功能,可以设定某一个消息在接收多次重新变得可见后进入到另一个 SQS 队列中。比如说队列 user-id-queue,设定了它的 Redrive Policy 为三次接收后转入到另一个 SQS 队列 user-id-dlq, 就会显示为

Maximum Receives 3
Dead Letter Queue arn:aws:sqs:us-east-1:<account_id>:user-id-dlq

在运用 SQS 的 DLQ 之前首先要理解 SQS 中消息的几个概念
  1. Message Available:  SQS 客户端可以获取到的消息, 即 Visible Messages
  2. Messages in Flight: 消息被 SQS 收取了之后,由 Available 转为 In Flight, 该状态的消息不能被客户端接收到
  3. Visibility Timeout:  消息停留在 In Flight 状态的时间, 如果在 Timeout 之前未删除这个消息,该消息重新变为 Available 状态

我们可以设置 SQS 队列的默认 Visibility Timeout 大小,也可以在代码中收取消息时指定这个值。

所以我们能够在集群环境中应用 SQS 的这个特性让多个节点同时监听单个 SQS 队列,基本上保证每个节点处理各自不同的消息。有一种例外就是:假设我们设置了 Visibility Timeout 是 30 秒,客户端 1 获取到消息后,消息变为 In Flight 状态,但 30 秒后仍然在处理过程中,此时消息回到Available 状态,客户端 2 也能获取到该消息,这也会造成单条消息的重复处理。解决的办法之一是适当延长 Visibility Timeout 的时间,给予第一个客户端更充分的处理时间。 阅读全文 >>