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() 消息?