Мне нужно проверить, существует ли набор ключей в S3 для каждого из большого количества элементов. (Каждый набор ключей относится к одному из большого количества элементов).
Я использую PHP SDK (v2)
В настоящее время я $client->doesObjectExist(BUCKET, $key)
для каждого из ключей, что является узким местом (время прохождения туда-обратно до S3 для каждого вызова).
Я бы предпочел сделать что-то вроде $client->doesObjectExist(BUCKET, $batch)
где $batch = array($key1, $key2 ... $keyn)
, и чтобы клиент мог проверить все эти ключи, массив ответов (или какой-либо другой подобной структуры).
Я столкнулся с несколькими ссылками на «пакетный апи», который звучит многообещающе, но ничего конкретного. Я предполагаю, что это могло присутствовать только в SDK v1.
Вы можете выполнять параллельные запросы, используя AWS SDK для PHP, используя основные функции библиотеки Guzzle. Поскольку метод 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"; }
Отправка команд в параллель упоминается в AWS SDK для руководства пользователя PHP , но я также хотел бы посмотреть документацию по пакетному документу Guzzle .
Единственный способ сделать массовую проверку, чтобы увидеть, существуют ли какие-то ключи, – это перечислить объекты в ведре.
Для вызова списка AWS возвращается до 1000 ключей / вызовов, поэтому он намного быстрее, чем выполнение вызова doesObjectExist
для каждого ключа. Но если у вас есть большое количество ключей, и вы хотите проверить только пару из них, то перечисление всех объектов в ведре не будет практичным, поэтому в этом случае вам остается только проверить каждый объект по отдельности.
Проблема заключается не в том, что в PHP v2 SDK отсутствует основная функциональность, а в том, что S3 API не реализует такую массовую обработку.
Я основываюсь на ответе Джереми Линдблома.
Просто хочу указать OnComplete
вызов 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
.