AWS Lambda发送部分响应

时间:2019-07-16 07:56:43

标签: amazon-web-services aws-lambda

我有一个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函数中可能吗?如果是这样,我们该怎么做。任何参考文档或示例代码都会有很大帮助。 谢谢。

4 个答案:

答案 0 :(得分:2)

据我了解,您正在使用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%确定无论该过程做什么,它都不会超出此硬限制。

答案 1 :(得分:1)

您正在寻找的是将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));
        }
    }
}

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

  

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

检查this link以获得更多详细信息:

  

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