【问题标题】:AWS lambda send partial responseAWS lambda 发送部分响应
【发布时间】:2019-08-27 20:03:22
【问题描述】:

我有一个执行一系列操作的 lambda 函数。我有一个触发 lambda 函数的反应应用程序。 有没有一种方法可以在每个操作完成后从 lambda 函数发送部分响应。

const testFunction = (event, context, callback) => {
    let partialResponse1 = await action1(event);
    // send partial response to client
    let partialResponse2 = await action2(partialResponse1);
    // send partial response to client  
    let partialResponse3 = await action3(partialResponse2);
    // send partial response to client
    let response = await action4(partialResponse3); 
    // send final response
}

这在 lambda 函数中可行吗?如果是这样,我们如何做到这一点。任何参考文档或示例代码都会有很大帮助。 谢谢。

注意:这是一个在客户端显示带有 % 的加载器的相当简单的例子。我不想让 SQS 或步进函数过于复杂。

我仍在寻找答案。

【问题讨论】:

  • 除非您使用消息队列之类的中间件,否则我认为这是不可能的。但这个问题很有趣。
  • 您的方法可能不正确。什么在调用 lambda?是 API 网关吗?
  • 对,就是API网关。

标签: amazon-web-services aws-lambda


【解决方案1】:

据我了解,您正在使用 API Gateway + Lambda,并希望通过 UI 显示 Lambda 的进度。

由于每个步骤都必须在下一步开始之前完成,我认为没有理由不调用 lambda 4 次,或者将 lambda 拆分为 4 个单独的 lambda。

例如:

// Not real syntax!

try {
  res1 = await ajax.post(/process, {stage: 1, data: ... });
  out(stage 1 complete);
  res2 = await ajax.post(/process, {stage: 2, data: res1});
  out(stage 2 complete);
  res3 = await ajax.post(/process, {stage: 3, data: res2});
  out(stage 3 complete);
  res4 = await ajax.post(/process, {stage: 4, data: res3});
  out(stage 4 complete);
  out(process finished);
catch(err) {
  out(stage {$err.stage-number} failed to complete);
}

如果您仍然希望在同一个 lambda 执行期间执行所有 4 个调用,您可以执行以下操作(如果进程预计很长,则尤其如此)(并且因为执行“长时间挂起”通常不是好习惯" http 事务)。

您可以通过将“进度”保存在数据库中来实现它,并在过程完成后将结果也保存到数据库中。

您需要做的就是每隔 X 秒查询一次状态。

// Not real syntax

Gateway-API --> lambda1 - startProcess(): returns ID {
  uuid = randomUUID();
  write to dynamoDB { status: starting }.
  send sqs-message-to-start-process(data, uuid);
  return response { uuid: uuid };
}

SQS --> lambda2 - execute(): returns void {
    try {
      let partialResponse1 = await action1(event);
      write to dynamoDB { status: action 1 complete }.
      // send partial response to client
      let partialResponse2 = await action2(partialResponse1);
      write to dynamoDB { status: action 2 complete }.
      // send partial response to client  
      let partialResponse3 = await action3(partialResponse2);
      write to dynamoDB { status: action 3 complete }.
      // send partial response to client
      let response = await action4(partialResponse3); 
      write to dynamoDB { status: action 4 complete, response: response }.
    } catch(err) {
      write to dynamoDB { status: failed, error: err }.
    }
}

Gateway-API --> lambda3 -> getStatus(uuid): returns status {
  return status from dynamoDB (uuid);
}

Your UI Code:

res = ajax.get(/startProcess);
uuid = res.uuid;

in interval every X (e.g. 3) seconds:
  status = ajax.get(/getStatus?uuid=uuid);
  show(status);
  if (status.error) {
    handle(status.error) and break;
  }
  if (status.response) {
    handle(status.response) and break;
  }
}

请记住,lambda 的执行时间不能超过 15 分钟。因此,您需要 100% 确定无论流程做什么,它都不会超过这个硬性限制。

【讨论】:

  • 感谢您的帮助。正如我所见,没有任何特定的方式可以从 lambda 函数返回部分响应。将状态写入数据库并检查固定间隔似乎是目前最好的选择。
  • 我确实为此确认了赏金。 :) 我不接受答案,因此如果 AWS 有任何更新,有人可能会发布或提供更多信息。
【解决方案2】:

您正在寻找的是让response 公开为流,您可以在其中写入流并刷新它

很遗憾,Node.js 中没有它

How to stream AWS Lambda response in node?

https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html

但如果您使用Java,您仍然可以进行流式传输

https://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html

package example;

import java.io.InputStream;
import java.io.OutputStream;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.amazonaws.services.lambda.runtime.Context; 

public class Hello implements RequestStreamHandler{
    public void handler(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        int letter;
        while((letter = inputStream.read()) != -1)
        {
            outputStream.write(Character.toUpperCase(letter));
        }
    }
}

【讨论】:

    【解决方案3】:

    阿曼, 您可以将部分输出推送到 SQS 并读取 SQS 消息以处理这些消息。这是一个简单且可扩展的架构。 AWS 提供不同语言的 SQS SDK,例如 JavaScript、Java、Python 等。

    使用 SDK 读取和写入 SQS 非常容易,并且也可以在服务器端或您的 UI 层(使用适当的 IAM)中实现。

    【讨论】:

    • 感谢您的信息。我会调查这个。 SQS 会将 msg 传递给客户端还是客户端必须定期检查 SQS 中的 msg?
    • 有两种方法可以实现这一点。您可以使用 SQS 触发器来触发 Lambda,因此只要在队列中收到消息,就会触发 AWS lambda。第二个选项是使用 AWS lambda 作为带有调度程序(来自 cloudwatch 调度程序)的队列侦听器。处理完消息后,必须手动清除队列。
    【解决方案4】:

    我发现AWS step function 可能是你需要的:

    AWS Step Functions 可让您将多个 AWS 服务协调到无服务器工作流程中,以便您可以快速构建和更新应用程序。

    查看this link了解更多详情:

    在我们的示例中,您是一名开发人员,他被要求创建一个无服务器应用程序来自动处理呼叫中心的支持工单。虽然您可以让一个 Lambda 函数调用另一个函数,但您担心随着呼叫中心应用程序变得更加复杂,管理所有这些连接将变得具有挑战性。此外,应用程序流程中的任何更改都需要在多个地方进行更改,并且您最终可能会一遍又一遍地编写相同的代码。

    【讨论】:

      猜你喜欢
      • 2015-10-21
      • 2015-09-29
      • 2020-09-27
      • 2020-04-03
      • 2014-10-28
      • 1970-01-01
      • 2016-09-14
      • 2021-10-23
      • 2019-07-17
      相关资源
      最近更新 更多