기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
AWS SDK for PHP 버전 3의 명령 객체
는 명령 패턴을
명령의 암시적 사용
클라이언트 클래스를 검사하면 API 작업에 해당하는 메서드가 실제로 존재하지 않음을 알 수 있습니다. 이러한 메서드는 __call()
magic 메서드를 사용하여 구현됩니다. 이러한 의사 방법은 실제로 SDK의 명령 객체 사용을 캡슐화하는 바로 가기입니다.
일반적으로 명령 객체와 직접 상호 작용할 필요는 없습니다. 와 같은 메서드를 호출하면 Aws\S3\S3Client::putObject()
는 제공된 파라미터를 기반으로 Aws\CommandInterface
객체를 SDK 실제로 생성하고 명령을 실행하며 채워진 Aws\ResultInterface
객체를 반환합니다(또는 오류 발생 시 예외 발생). 클라이언트의 Async
메서드(예: Aws\S3\S3Client::putObjectAsync()
) 중 하나를 호출할 때 유사한 흐름이 발생합니다. 클라이언트는 제공된 파라미터를 기반으로 명령을 생성하고, HTTP 요청을 직렬화하고, 요청을 시작하고, 약속을 반환합니다.
다음은 기능적으로 동등한 예제입니다.
$s3Client = new Aws\S3\S3Client([ 'version' => '2006-03-01', 'region' => 'us-standard' ]); $params = [ 'Bucket' => 'foo', 'Key' => 'baz', 'Body' => 'bar' ]; // Using operation methods creates a command implicitly $result = $s3Client->putObject($params); // Using commands explicitly $command = $s3Client->getCommand('PutObject', $params); $result = $s3Client->execute($command);
명령 파라미터
모든 명령은 서비스의 일부가 아니라 SDK의 동작을 API 제어하는 몇 가지 특수 파라미터를 지원합니다.
@http
이 파라미터를 사용하면 기본 HTTP 핸들러가 요청을 실행하는 방법을 미세 조정할 수 있습니다. @http
파라미터에 포함시킬 수 있는 옵션은 “http” 클라이언트 옵션을 사용하여 클라이언트를 인스턴스화할 때 설정할 수 있는 옵션과 동일합니다.
// Configures the command to be delayed by 500 milliseconds $command['@http'] = [ 'delay' => 500, ];
@retries
“재시도” 클라이언트 옵션과 마찬가지로, @retries
는 실패한 것으로 간주되기 전에 명령을 재시도할 수 있는 횟수를 제어합니다. 재시도를 비활성화하려면 이 옵션을 0
으로 설정합니다.
// Disable retries $command['@retries'] = 0;
참고
클라이언트에서 재시도를 비활성화한 경우 해당 클라이언트에 전달된 개별 명령에서 재시도를 선택적으로 활성화할 수 없습니다.
명령 객체 생성
클라이언트의 getCommand()
메서드를 사용하여 명령을 생성할 수 있습니다. 즉시 HTTP 요청을 실행하거나 전송하지는 않지만 클라이언트의 execute()
메서드에 전달될 때만 실행됩니다. 따라서 명령을 실행하기 전에 명령 객체를 수정할 기회가 있습니다.
$command = $s3Client->getCommand('ListObjects'); $command['MaxKeys'] = 50; $command['Prefix'] = 'foo/baz/'; $result = $s3Client->execute($command); // You can also modify parameters $command = $s3Client->getCommand('ListObjects', [ 'MaxKeys' => 50, 'Prefix' => 'foo/baz/', ]); $command['MaxKeys'] = 100; $result = $s3Client->execute($command);
명령 HandlerList
클라이언트에서 명령을 생성한 경우 클라이언트 Aws\HandlerList
객체의 복제가 명령에 제공됩니다. 명령이 클라이언트에서 실행하는 다른 명령에 영향을 미치지 않는 사용자 지정 미들웨어와 핸들러를 사용할 수 있도록 클라이언트 핸들러 목록의 복제가 명령에 제공됩니다.
즉, 명령당 다른 HTTP 클라이언트(예: Aws\MockHandler
)를 사용하고 미들웨어를 통해 명령당 사용자 지정 동작을 추가할 수 있습니다. 다음 예제에서는 실제 HTTP 요청을 보내는 대신 MockHandler
를 사용하여 모의 결과를 생성합니다.
use Aws\Result; use Aws\MockHandler; // Create a mock handler $mock = new MockHandler(); // Enqueue a mock result to the handler $mock->append(new Result(['foo' => 'bar'])); // Create a "ListObjects" command $command = $s3Client->getCommand('ListObjects'); // Associate the mock handler with the command $command->getHandlerList()->setHandler($mock); // Executing the command will use the mock handler, which returns the // mocked result object $result = $client->execute($command); echo $result['foo']; // Outputs 'bar'
명령에 사용되는 핸들러를 변경할 수 있을 뿐 아니라, 사용자 지정 미들웨어를 명령에 주입할 수도 있습니다. 다음 예제에서는 핸들러 목록에서 관찰자로 작동하는 tap
미들웨어를 사용합니다.
use Aws\CommandInterface; use Aws\Middleware; use Psr\Http\Message\RequestInterface; $command = $s3Client->getCommand('ListObjects'); $list = $command->getHandlerList(); // Create a middleware that just dumps the command and request that is // about to be sent $middleware = Middleware::tap( function (CommandInterface $command, RequestInterface $request) { var_dump($command->toArray()); var_dump($request); } ); // Append the middleware to the "sign" step of the handler list. The sign // step is the last step before transferring an HTTP request. $list->append('sign', $middleware); // Now transfer the command and see the var_dump data $s3Client->execute($command);
CommandPool
Aws\CommandPool
을 사용하면 Aws\CommandInterface
객체를 산출하는 반복자를 사용하여 명령을 동시에 실행할 수 있습니다. CommandPool
은 풀의 명령을 반복하는 동안 일정한 수의 명령이 동시에 실행되도록 보장합니다(명령이 완료되면 일정한 풀 크기를 유지하기 위해 추가 명령이 실행됨).
다음은 CommandPool
을 사용하여 몇 개의 명령만 전송하는 매우 간단한 예제입니다.
use Aws\S3\S3Client; use Aws\CommandPool; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $bucket = 'example'; $commands = [ $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'a']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'b']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'c']) ]; $pool = new CommandPool($client, $commands); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait();
이 예제는 CommandPool
의 성능을 상당히 낮춘 것입니다. 더 복잡한 예제를 살펴보겠습니다. 디스크의 파일을 Amazon S3 버킷에 업로드한다고 가정합니다. 디스크에서 파일 목록을 가져오려면 PHP의 를 사용할 수 있습니다DirectoryIterator
. 이 반복자는 SplFileInfo
객체를 생성합니다. CommandPool
은 Aws\CommandInterface
객체를 산출하는 반복자를 받으므로, Aws\CommandInterface
객체를 반환하도록 SplFileInfo
객체를 매핑합니다.
<?php require 'vendor/autoload.php'; use Aws\Exception\AwsException; use Aws\S3\S3Client; use Aws\CommandPool; use Aws\CommandInterface; use Aws\ResultInterface; use GuzzleHttp\Promise\PromiseInterface; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $fromDir = '/path/to/dir'; $toBucket = 'amzn-s3-demo-bucket'; // Create an iterator that yields files from a directory $files = new DirectoryIterator($fromDir); // Create a generator that converts the SplFileInfo objects into // Aws\CommandInterface objects. This generator accepts the iterator that // yields files and the name of the bucket to upload the files to. $commandGenerator = function (\Iterator $files, $bucket) use ($client) { foreach ($files as $file) { // Skip "." and ".." files if ($file->isDot()) { continue; } $filename = $file->getPath() . '/' . $file->getFilename(); // Yield a command that is executed by the pool yield $client->getCommand('PutObject', [ 'Bucket' => $bucket, 'Key' => $file->getBaseName(), 'Body' => fopen($filename, 'r') ]); } }; // Now create the generator using the files iterator $commands = $commandGenerator($files, $toBucket); // Create a pool and provide an optional array of configuration $pool = new CommandPool($client, $commands, [ // Only send 5 files at a time (this is set to 25 by default) 'concurrency' => 5, // Invoke this function before executing each command 'before' => function (CommandInterface $cmd, $iterKey) { echo "About to send {$iterKey}: " . print_r($cmd->toArray(), true) . "\n"; }, // Invoke this function for each successful transfer 'fulfilled' => function ( ResultInterface $result, $iterKey, PromiseInterface $aggregatePromise ) { echo "Completed {$iterKey}: {$result}\n"; }, // Invoke this function for each failed transfer 'rejected' => function ( AwsException $reason, $iterKey, PromiseInterface $aggregatePromise ) { echo "Failed {$iterKey}: {$reason}\n"; }, ]); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait(); // Or you can chain the calls off of the pool $promise->then(function() { echo "Done\n"; });
CommandPool
구성
Aws\CommandPool
생성자는 다양한 구성 옵션을 받습니다.
- concurrency (callable|int)
-
동시에 실행할 최대 명령 수입니다. 동적으로 풀 크기를 조정하려면 함수를 제공합니다. 함수에는 현재 보류 중인 요청 수가 제공되며 이 함수는 새 풀 크기 한도를 나타내는 정수를 반환할 것으로 예상됩니다.
- before (callable)
-
각 명령을 전송하기 전에 호출할 함수입니다.
before
함수는 명령과 명령의 반복자 키를 받습니다. 명령을 전송하기 전에before
함수에서 필요에 따라 명령을 변형할 수 있습니다. - fulfilled (callable)
-
promise가 이행될 때 호출할 함수입니다. 결과 객체, 결과가 나온 반복자의 ID, 풀을 단락시켜야 하는 경우 해결하거나 거부할 수 있는 집계 promise가 함수에 제공됩니다.
- rejected (callable)
-
promise가 거부될 때 호출할 함수입니다.
Aws\Exception
객체, 예외가 나온 반복자의 ID, 풀을 단락시켜야 하는 경우 해결하거나 거부할 수 있는 집계 promise가 함수에 제공됩니다.
명령 간 수동 가비지 수집
큰 명령 풀로 메모리 제한에 도달하는 경우 메모리 제한에 도달했을 때 PHP 가비지 수집기가CommandPool
을 생성하는 것입니다. 단, 가비지 수집기를 호출할 경우 성능 비용이 발생하므로 사용 사례와 환경에 따라 사용하는 것이 좋습니다.
$pool = new CommandPool($client, $commands, [ 'concurrency' => 25, 'before' => function (CommandInterface $cmd, $iterKey) { gc_collect_cycles(); } ]);