AWS SDK (PHP):异步调用 lambda 函数,检索状态

Posted

技术标签:

【中文标题】AWS SDK (PHP):异步调用 lambda 函数,检索状态【英文标题】:AWS SDK (PHP): Invoking lambda function asynchronously, retrieving status 【发布时间】:2016-10-30 21:06:51 【问题描述】:

我们有一个 AWS lambda 函数,用于在下载加载之前进行一些糟糕的专有文件格式处理和自定义,这是通过 AWS 开发工具包从 php 触发的。 lambda 从 s3 存储桶中抓取文件,将一些元数据插入文件中,对其进行压缩,然后将其放在 s3 上的一个临时存储桶中,以便在客户结账时下载。

lambda 部分通过invoke/invokeAsync 完美运行:

use Aws\Sdk;
...
$lambdaclient = $this->sdk->createClient('lambda',$region);

$syncresult = $lambdaclient->invoke([
    'FunctionName' => $functionName,
    'InvocationType' => 'RequestResponse',
    'Payload' => json_encode($payload),
]);

$asyncresult = $lambdaclient->invoke([
    'FunctionName' => $functionName,
    'InvocationType' => 'Event',
    'Payload' => json_encode($payload),
]);

$promise = $lambdaclient->invokeAsync([
    'FunctionName' => $functionName,
    'Payload' => json_encode($payload),
]);
$syncresult 将包含 lambda 函数的成功/失败状态,可选择使用日志(通过 LogType Tail)。

问题是 lambda 可能需要一分钟才能完成,这对于 PHP 向浏览器返回响应来说相当长。

$asyncresult 将调用该函数,并返回 HTTP 状态 202,但无法稍后检查该函数是否实际执行任何操作。

$promise 是一个 Guzzle promise,被 AWS 开发工具包广泛使用,可以在 PHP 中绑定一个函数,以便在 lambda 完成时执行。这似乎非常有用,只要 PHP 不向浏览器返回响应,因为此时您失去了承诺。您可以致电$result = $promise->wait() 让它解决。这些 Promise 的主要优势似乎是同时运行多个 lambda,并将结果组合在一起,所有这些都在一个 PHP 请求中。

我想要异步调用函数,并在稍后 PHP 请求中检查函数状态(也许在会话数据中存储一些对调用的引用?)。这样,我可以稍后使用 Ajax 请求轮询状态,并确保当我为最终文件创建签名的 s3 URL 时,一切都完成且没有错误。

使用 AWS 开发工具包可以实现这样的事情吗?还是有更好的解决方案?

编辑:

我决定使用从被中止的客户端 ajax 调用触发的 invokeAsync(不等待应答)。 PHP 脚本有相当长的时间来完成(使用 settimelimit),因为对 lambda 的调用是同时运行的,并且浏览器不再等待。

我将承诺存储在一个数组中,并使用:

$values = array_map(function($result)
    return json_decode($result->toArray()['Payload']->getContents());
, Promise\unwrap($promises));

获取响应负载(它们被 AWS SDK 包装在流接口中),并将它们写掉(在我的例子中,DynamoDB 通过 SQL/session/cache 可能都可以工作)。

当最终用户需要结果时,我只是简单地检查存储的数据以及转换后的文件是否存在于 s3 上。

我可能会改进 ajax 处理,方法是从 PHP 刷新输出缓冲区,使用返回的一些 ID 正确完成调用,同时允许 PHP 等待来自 AWS 的承诺。

【问题讨论】:

【参考方案1】:

是的,你可以做到这一点,但我不确定你是否可以纯粹使用 Lambda 做到这一点。我的处理方式是这样的:

1) 当您当前的 PHP 代码被点击时,添加使用 AWS SNS 发送一条消息,其中包含有关函数和参数的详细信息。立即向浏览器返回一条消息,其中包含有关要在 s3 中监视的文件的信息。然后让您的浏览器轮询我在步骤 3 中描述的端点。

2) 设置您的 lambda 函数以侦听 SNS 消息并自动运行 (http://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html)

3) 有另一个 PHP 端点,您可以使用 AJAX 访问该端点,以检查 lambda 创建的文件是否已创建完成。如果没有返回一条消息说它还没有准备好,一旦文件存在然后返回一条消息说它已经准备好了。

如果您不想使用纯粹的 AWS 方法,那么您可以这样做:

1) 当您当前的 PHP 代码被命中时,将记录添加到数据库表中,其中包含有关需要运行的函数和参数的信息以及类似 queued 的状态。立即将数据库中记录的id 发送回浏览器。然后让您的浏览器轮询我在步骤 3 中描述的端点。

2) 设置一个单独的 php 脚本,该脚本连续运行或通过 cron 或其他东西触发,每隔几秒检查一次上面创建的表中状态为 queued 的条目。将记录状态更新为processing 之类的内容,这样它就不会意外再次运行。现在让它触发 Lambda 函数并使用 Promise。完成后,将记录状态更新为complete

3) 有另一个 PHP 端点,您可以使用 AJAX 访问该端点,您可以传入在第一步中收到的 id 并简单地返回记录的状态。一旦浏览器返回complete 的状态,它就知道文件已准备好下载。

【讨论】:

谢谢,您的答案略有不同(见编辑)!标记为已接受。

以上是关于AWS SDK (PHP):异步调用 lambda 函数,检索状态的主要内容,如果未能解决你的问题,请参考以下文章

鉴于所有调用都是异步的,您如何在 lambda 中构建顺序 AWS 服务调用?

使用 AWS SDK for Java 调用 AWS Lambda 函数时如何检索 context.done() 消息?

有时,我的 AWS lambda 函数没有使用调用异步运行

如何在 AWS Lambda 中运行 AWS SDK Opsworks 命令?

AWS Lambda 异步并发限制

使用 AWS-cpp-sdk 时,在退出程序之前等待异步调用返回