我需要检查S3中是否存在大量项中的每个项的一组密钥。(每组密钥都与大量项中的一项相关)。
我正在使用PHP (v2)
目前,我正在为每个键调用$client->doesObjectExist(BUCKET, $key)
,这是一个瓶颈(每个呼叫从S3到S3的往返时间)。
我更喜欢执行类似于$client->doesObjectExist(BUCKET, $batch)
where $batch = array($key1, $key2 ... $keyn)
的操作,并让客户端检查所有这些键,然后返回一个响应数组(或其他类似的结构)。
我遇到了一个一些 参考文献,它是一个“批处理api”,听起来很有希望,但没有任何具体内容。我猜这可能只出现在v1 SDK中。
发布于 2013-09-05 20:52:46
您可以使用AWS通过利用底层的口吻库特性来执行并行请求。因为doesObjectExist
方法实际上在这个遮罩下执行HeadObject
操作。您可以通过这样的操作创建HeadObject命令组:
use Aws\S3\S3Client;
use Guzzle\Service\Exception\CommandTransferException;
function doObjectsExist(S3Client $s3, $bucket, array $objectKeys)
{
$headObjectCommands = array();
foreach ($objectKeys as $key) {
$headObjectCommands[] = $s3->getCommand('HeadObject', array(
'Bucket' => $bucket,
'Key' => $key
));
}
try {
$s3->execute($headObjectCommands); // Executes in parallel
return true;
} catch (CommandTransferException $e) {
return false;
}
}
$s3 = S3Client::factory(array(
'key' => 'your_aws_access_key_id',
'bucket' => 'your_aws_secret_key',
));
$bucket = 'your_bucket_name';
$objectKeys = array('object_key_1', 'object_key_2','object_key_3');
// Returns true only if ALL of the objects exist
echo doObjectsExist($s3, $bucket, $objectKeys) ? 'YES' : 'NO';
如果您想要响应中的数据,而不仅仅是键是否存在,您可以更改try-catch块来执行类似的操作。
try {
$executedCommands = $s3->execute($headObjectCommands);
} catch (CommandTransferException $e) {
$executedCommands = $e->getAllCommands();
}
// Do stuff with the command objects
foreach ($executedCommands as $command) {
$exists = $command->getResponse()->isSuccessful() ? "YES" : "NO";
echo "{$command['Bucket']}/{$command['Key']}: {$exists}\n";
}
在用于PHP用户指南的AWS SDK中提到并行发送命令,但我也会查看炮口批次文件。
发布于 2013-09-05 14:08:17
进行大容量检查以确定是否存在某些键的唯一方法是列出桶中的对象。
对于一个列表调用,AWS最多返回1000个键/调用,因此比对每个键执行doesObjectExist
调用要快得多。但是,如果您有大量的键,并且只想检查其中的几个,那么列出桶中的所有对象是不实际的,所以在这种情况下,您唯一的选择仍然是单独检查每个对象。
问题不是PHP缺少批量功能,而是v2 S3没有实现这样的批量处理。
发布于 2015-01-30 03:12:17
我是建立在杰里米·林德布罗姆的回答之上的。
只想指出可以在每个命令上设置的OnComplete
回调。
$bucket = 'my-bucket';
$keys = array('page1.txt', 'page2.txt');
$commands = array();
foreach ($keys as $key) {
$commands[] = $s3Client->getCommand('HeadObject', array('Bucket' => $bucket, 'Key' => $key))
->setOnComplete(
function($command) use ($bucket, $key)
{
echo "\nBucket: $bucket\n";
echo "\nKey: $key\n";
// see http://goo.gl/pIWoYr for more detail on command objects
var_dump($command->getResult());
}
);
}
try {
$ex_commands = $s3Client->execute($commands);
}
catch (\Guzzle\Service\Exception\CommandTransferException $e) {
$ex_commands = $e->getAllCommands();
}
// this is necesary; without this, the OnComplete handlers wouldn't get called (strange?!?)
foreach ($ex_commands as $command)
{
$command->getResult();
}
如果有人能解释我为什么需要调用$command->getResult()
来调用OnComplete
处理程序,那就太好了。
https://stackoverflow.com/questions/18638463
复制相似问题