【问题标题】:AWS Lambda not removing messages from the queueAWS Lambda 未从队列中删除消息
【发布时间】:2019-07-12 17:18:32
【问题描述】:

我正在使用以下代码从 SQS 事件触发 Lambda 函数:

@Override
public Void handleRequest(SQSEvent sqsEvent, Context context) {
    for (SQSMessage sqsMessage : sqsEvent.getRecords()) {
        final String body = sqsMessage.getBody();
        try {
            //do stuff here
        } catch (Exception ex) {
            //send to DLQ
        }
    }
    return null;
}

“做事”正在使用以下代码调用另一个 Lambda 函数:

private final AWSLambda client;
    private final String functionName;

    public LambdaService(AWSLambdaAsync client, String functionName) {
        this.client = client;
        this.functionName = functionName;
    }

    public void runWithPayload(String payload) {
        logger.info("Invoking lambda {} with payload {}", functionName, payload);
        final InvokeRequest request = new InvokeRequest();
        request.withFunctionName(functionName).withPayload(payload);
        final InvokeResult invokeResult = client.invoke(request);
        final Integer statusCode = invokeResult.getStatusCode();
        logger.info("Invoked lambda {} with payload {}. Got status code {} and response payload {}",
                functionName,
                payload,
                statusCode,
                StandardCharsets.UTF_8.decode(invokeResult.getPayload()).toString());
        if(statusCode.equals(200) == false) {
            throw new IllegalStateException(String.format("There was an error executing the lambda function %s with payload %s", functionName, payload));
        }
    }

我正在使用以下库:

<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-lambda-java-core</artifactId>
  <version>1.2.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-lambda-java-events</artifactId>
  <version>2.2.6</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-java-sdk-sqs</artifactId>
  <version>1.11.505</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-java-sdk-lambda</artifactId>
  <version>1.11.505</version>
</dependency>

问题在于,看起来 SQS 消息并未从队列中删除,而是被一遍又一遍地重新处理。它每 30 秒发生一次,这正是 Default Visibility Timeout 的值。现在,据我所知,如果使用 sqs 消息的 lambda 正确终止,它应该自动从队列中删除该消息,但这并没有发生。 我认为 lambda 中没有发生任何错误,因为我在 DLQ 中没有收到任何消息(并且我有一个包罗万象的块),并且我在 Cloudwatch 的日志中看不到任何堆栈跟踪。我对这里发生的事情有点困惑,有人有什么好主意吗?

【问题讨论】:

  • 我唯一能看到的是 Lambda 函数所承担的角色没有权限在源队列上调用 sqs:DeleteMessage。会是这样吗?
  • @ThalesMinussi 这是个好主意,我会仔细检查,但如果是这种情况,我会收到错误消息。
  • 如果您的角色没有删除消息的权限,我不确定您是否能够创建 SQS 事件源。如果未设置正确的权限,我知道如果我尝试使用 Terraform 创建事件源会失败。由于 Terraform 只使用 API 调用,我认为它也应该在控制台中失败。但也许在创建事件源时,角色具有权限,然后权限被删除。我不认为它应该出错,因为“删除”消息的代码不是你的函数本身的一部分,但我可能错了。
  • 好的!这已经启发了我的道路一点点!由于这似乎是一个随机问题(意味着某些消息确实被删除),我敢打赌可见性超时。也许您的 Lambda 处理时间超过 30 秒(考虑到您的 Lambda 有这么长的超时时间),但 VT 只有 30 秒,这使得消息再次可见,而一个 Lambda 仍在处理它。所以你有点陷入循环,最终,它们被删除。我会先尝试检查这些事情:消息处理时间和可见性超时。开始时可能会增加到 5 分钟左右
  • 这些都是好消息!是的,绝对值得看看为什么你的函数运行了这么长时间,但我很高兴我们已经部分解决了这个问题

标签: java amazon-web-services aws-lambda aws-sdk amazon-sqs


【解决方案1】:

除非最近发生了变化,否则我认为适用于 Java 的 AWS 开发工具包不会自动从队列中删除消息。你需要编写代码来做到这一点。

我很想被证明是错误的,请分享我错过的文档摘录。

代码示例:

【讨论】:

  • 如果 Lambda 由 SQS 事件触发,它应该自动删除消息,不是吗?至少这是在 Node.js 中发生的事情,但我认为该平台应该不会删除消息,因为这一切都归结为 API 调用。
  • "Lambda 轮询队列并与包含队列消息的事件同步调用您的函数。Lambda 分批读取消息并为每个批次调用一次您的函数。当您的函数成功处理一个批次时,Lambda 删除它来自队列的消息。” -> docs.aws.amazon.com/lambda/latest/dg/with-sqs.html
  • @SébastienStormacq 您链接了 sqs-sdk,但我没有使用它,我使用的是 com.amazonaws.services.lambda.runtime.events.SQSEvent。该文档是@ThalesMinussi 粘贴的。
  • 感谢您的澄清。我错过了它是 Lambda SQS 触发器而不是常规 Lambda SQS 客户端的事实。
猜你喜欢
  • 2020-03-24
  • 1970-01-01
  • 2016-04-29
  • 2021-04-20
  • 2020-07-10
  • 1970-01-01
  • 2015-10-18
  • 2014-06-07
  • 2015-12-20
相关资源
最近更新 更多