【发布时间】: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