【发布时间】: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 的承诺。
【问题讨论】:
标签: php amazon-web-services amazon-s3 aws-sdk aws-lambda