我们有一个AWS lambda函数,用于在 down 加载之前进行一些可怕的专有文件格式处理和自定义,这是通过AWS SDK从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),
]);
问题是lambda可能需要一分钟才能完成,这对PHP来说很长时间才能返回对浏览器的响应。
$ asyncresult将调用该函数,并返回HTTP状态202,但无法在以后检查该函数是否实际执行了任何操作。
$ promise是一个Guzzle promise,由AWS SDK广泛使用,当lambda完成时,可以在PHP中绑定一个函数来执行。这似乎非常有用,只要PHP不返回对浏览器的响应,因为那时你就失去了承诺。您可以致电$result = $promise->wait()
让它解决。这些承诺的主要优点似乎是同时运行多个lambda,并将结果组合在一起,所有这些都在一个PHP请求中。
我想要的是异步调用函数,并在以后的 PHP请求中检查函数状态(可能会在会话数据中存储一些对调用的引用?)。这样,我可以稍后使用Ajax请求轮询状态,并确保当我创建一个签名的s3 URL到最终文件时,所有内容都完成而没有错误。
使用AWS SDK可以做到这一点吗?或者有更好的解决方案吗?
我决定使用从客户端ajax调用触发的invokeAsync,该调用被中止(不等待答案)。 PHP脚本有相当大的时间来完成(使用settimelimit),因为对lambda的调用是并发运行的,浏览器不再等待了。
我将promises存储在一个Array中,并使用:
$values = array_map(function($result){
return json_decode($result->toArray()['Payload']->getContents());
}, Promise\unwrap($promises));
获取响应有效负载(它们由AWS SDK封装在流接口中),然后将它们写出来(在我的情况下,使用DynamoDB,通过SQL /会话/缓存可能都可以工作)。
当最终用户需要结果时,我只是清楚地检查存储的数据以及转换后的文件是否存在于s3上。
我可以通过从PHP刷新输出缓冲区来改进ajax处理,使用一些返回的ID正确完成调用,同时允许PHP等待AWS的承诺。
答案 0 :(得分:1)
是的,你可以这样做我不确定你是否可以纯粹使用Lambda。我接近它的方式是:
1)当您的当前PHP代码被点击时,添加发送带有AWS SNS的消息,其中包含有关功能和参数的详细信息。立即向浏览器返回一条消息,其中包含有关要在s3中查看的文件的信息。然后让您的浏览器轮询我在步骤3中描述的端点。
2)设置lambda函数以侦听SNS消息并自动运行(http://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html)
3)有另一个可以用AJAX命中的PHP端点,它检查lambda创建的文件是否已经完成。如果没有返回一条消息,表示它还没有准备就绪,一旦文件存在,则返回一条消息,说明它已准备就绪。
如果您不想使用纯粹的AWS方法,那么您可以执行以下操作:
1)当您的当前PHP代码被命中时,在数据库表中添加一条记录,其中包含有关需要运行的函数和参数以及queued
之类的状态的信息。立即将数据库中的记录id
发送回浏览器。然后让您的浏览器轮询我在步骤3中描述的端点。
2)设置一个单独的php脚本,该脚本连续运行或通过cron或其他东西触发,每隔几秒检查上面创建的表的条目,状态为queued
。将记录状态更新为processing
,以免意外再次运行。现在让它触发Lambda函数并使用promise。完成后,将记录状态更新为complete
。
3)有另一个PHP端点,你可以使用AJAX命中你传入第一步中收到的id,然后只返回记录的状态。一旦浏览器返回状态complete
,它就知道该文件已准备好下载。