Services_Amazon_SQSを触ってみた
Amazon SQS (Amazon Simple Queue Service) は、Amazonが提供するジョブキューイング用なメッセージ格納のキューです。
ここでは詳しい説明は、省略します。これ単体で使うというよりは、EC2で処理させて、スケーラブルに処理を捌くというのが用途かと思います。
で、これを扱うためのPEARライブラリとして、Services_Amazon_SQSがあります。
2010年1月現在、バージョン0.3がベータ版として提供されています。
また、このPEARパッケージは、いわゆるPEARライブラリのほかに、コマンドラインから実行してSQSを操作できるコマンドラインツールが同梱されています。
ちなみに、AmazonでもPHP用のサンプルコードを提供しています。
- http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1287&categoryID=30
- http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31: ドキュメント中に利用方法が書いてある
まずインストール
PEARコマンドでさっくりインストール。
sudo pear install Services_Amazon_SQS-0.3.0 Password: Failed to download pear/Crypt_HMAC2 within preferred state "stable", latest release is version 0.2.1, stability "beta", use "channel://pear.php.net/Crypt_HMAC2-0.2.1" to install Failed to download pear/Net_URL2 within preferred state "stable", latest release is version 0.3.0, stability "beta", use "channel://pear.php.net/Net_URL2-0.3.0" to install Failed to download pear/HTTP_Request2 within preferred state "stable", latest release is version 0.5.1, stability "alpha", use "channel://pear.php.net/HTTP_Request2-0.5.1" to install pear/Services_Amazon_SQS requires package "pear/Crypt_HMAC2" (version >= 0.2.1) pear/Services_Amazon_SQS requires package "pear/Net_URL2" (version >= 0.2.0) pear/Services_Amazon_SQS requires package "pear/HTTP_Request2" (version >= 0.1.0) downloading Console_CommandLine-1.1.1.tgz ... Starting to download Console_CommandLine-1.1.1.tgz (38,054 bytes) ..........done: 38,054 bytes install ok: channel://pear.php.net/Console_CommandLine-1.1.1
ということで、依存関係のあるパッケージがベータで拾えずに失敗しているので、個別にインストール。
pear install Crypt_HMAC2-beta Net_URL2-beta HTTP_Request2-alpha Services_Amazon_SQS-0.3.0
Amazon SQSの利用登録
SQSは、有償サービスであり、登録が必要です。
から、"Sign Up for Amazon SQS" をクリックして、登録を完了してください。
ちなみに、利用料は、以下となっています。ちょっと試す程度であれば数ドル程度です。
コマンドラインツールの実行
コマンドラインツールは、sqsという名前です。コマンドラインツールは、PEARのbin_dirにインストールされますので、以下でパスを調べることができます。
$ pear config-get bin_dir /path/to/php/bin
設定ファイルの準備
設定ファイルに、Amazonのアクセスキーの設定が必要です。設定してない状態で起動すると、設定ファイルのパスが表示されます。
$ sqs Access key id is missing from configuration file. Please set your Amazon Web Services access key id in the "access_key" field in the file "/path/to/sqs.ini".
ファイルの内容はこのようになっています。
; This file contains the access keys for your Amazon Web Services (AWS) account ; to be used by the PEAR Services_Amazon_SQS package. The Services_Amazon_SQS ; package is fully useable without entering this information but the provided ; 'sqs' command-line application requires this configuration file to be ; completed. ; ; See http://pear.php.net/packages/Services_Amazon_SQS for details. ; ; You can get your AWS access keys by going to http://aws.amazon.com/account/ ; and clicking on the 'Access Identifiers' link. To use the SQS, you must ; have signed up for the service at http://aws.amazon.com/sqs/. ; Your AWS Access Key ID. Your Access Key ID identifies you as the party ; responsible for the request. ;access_key = "YOUR-AWS-ACCESS-KEY-HERE" ; Your AWS Secret Access Key ID. Your Secret Access Key ID is used to sign ; requests for web services that require authenticated requests. ;secret_access_key = "YOUR-AWS-SECRET-ACCESS-KEY-HERE"
access_key と secret_access_key の行の先頭のコメント ( ; ) を外して、自身のアクセスキーを入力してください。
起動
起動に成功するとこんな感じで使い方のヘルプができます。
$ sqs A command-line interface to Amazon's Simple Queue Service (SQS). Usage: /path/to/sqs [options] /path/to/sqs [options] <command> [options] [args] Options: -c config, --config=config Find configuration in "config". Commands: create Creates a new queue with the specified name. The queue may take up to 60 seconds to become available. delete Deletes an existing queue by the specified URI. The queue may take up to 60 seconds to become unavailable. help Displays an overview of available options and commands, or detailed help for a specific command. list Lists available queues. If a prefix is specified, only queues beginning with the specified prefix are listed. send Sends input from STDIN to the specified queue. The resulting message identifier is displayed on STDOUT. receive Receives a message from the specified queue. The message body is displayed on STDOUT. If no message is received, nothing is displayed on STDOUT. version Displays version information and exits.
ざっくり訳すと、
$ sqs Amazon Simple Queue Service (SQS)のコマンドラインインターフェイス 使用法: /path/to/sqs [オプション] /path/to/sqs [オプション] <コマンド> [オプション] [引数] オプション: -c config, --config=config "config"で指定した設定項目の値を表示 Commands: create 指定した名称で新しいキューを作成する。キューが利用可能になる まで60秒ほど時間がかかる。 delete 指定したURIの既存のキューを削除する。キューが利用不能になる まで60秒ほど時間がかかる。 help 利用可能なオプションとコマンドの概要を表示する、もしくは 指定したコマンドのヘルプを表示する list 利用可能なキューの一覧を表示する。prefixを指定した場合、その prefixから始まるキューのみを一覧に表示する。 send 指定したキューへ、標準入力(STDIN)からの入力を送信する。 結果のメッセージ識別子は、標準出力(STDOUT)に表示される。 receive 指定したキューからメッセージを受信する。メッセージ本文は、 標準出力に表示される。もし、メッセージが受信されない場合、 標準出力には何も表示されない。 version バージョン情報を表示する。
キューの作成 (create)
sqs create [キュー名] で作成。
$ sqs create test-queue Queue "http://queue.amazonaws.com/508403871985/test-queue" has been added. It may take up to 60 seconds for the new queue to appear in the list of queues.
キューの作成 (delete)
sqs delete [キューのURI] で削除。
sqs delete "http://queue.amazonaws.com/508403871985/test-queue" Queue has been deleted. It may take up to 60 seconds for the queue list to reflect this change.
キューの一覧表示 (list)
sqs list。要素数と、可視タイムアウト(visibility timeout)が表示される。(visibility timeoutはキューの作成時に、指定できる)
$ sqs list ITEMS VIS. QUEUE NAME (APPROX.) TIMEOUT http://queue.amazonaws.com/508403871985/test-queue 4 30
visibility timeoutは、キューからデータを取得したときに、そのデータをロックする時間。例えば、クライアントAが、キューからデータ1を取得したタイミングで、visibility timeoutの秒数の間、データ1はロックされ、他のクライアントから取得されたりしない。この間に、クライアントAはデータ処理を行って、データ1を削除する。もし、クライアントAで問題が起きて、visibility timeoutの間に、削除できなかった場合、キューにデータ1は復活する。
キューへの要素の追加 (send)
sqs send [キューのURI] で標準入力で渡したデータをキューに追加。
$ echo 1 | sqs send "http://queue.amazonaws.com/508403871985/test-queue" 2ee91df9-2292-45f2-8c92-76ad2c6b8046 $ echo 2 | sqs send "http://queue.amazonaws.com/508403871985/test-queue" 1e6e135a-b287-41c3-af05-9d9298585ef1
メッセージは最大8KBまで格納できます。追加が成功すると、メッセージIDというのが表示されます。
なお、マルチバイト文字列を送ろうとするとエラーになります。ライブラリの仕様と、SQSの隠れ仕様で、この問題が起きてます。以下は、試しにdateコマンドの出力を流した場合。
date | sqs send "http://queue.amazonaws.com/508403871985/test-queue" The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
キューの要素の取得 (receive)
sqs receive [キューのURI] で、データを出力します。また、-d オプションで受信したデータを削除することができます。
$ sqs receive "http://queue.amazonaws.com/508403871985/test-queue" 1 $ sqs receive "http://queue.amazonaws.com/508403871985/test-queue" 2
ライブラリの利用
キューの作成などももちろんできますが、送信と受信処理についてだけ。
受信時の戻り値
receive()は、成功時、以下のような配列を返却します。データが取得できない場合は空配列を受け取ります。
array(1) { [0]=> array(3) { ["id"]=> string(36) "f6f79090-8a26-469f-89a3-2162c571f7e5" ["body"]=> string(2) "2 " ["handle"]=> string(172) "+eXJYhj5rDri2De+UILzboaz4QxJnnN7vk0KSUVNAbl0DJ3gVOmjI2Gh/oFnb0IeJqy5Zc8kH4JWc6Thp2AWPDaAPSeOkXQZMXPJOvFfdxLavSb3vNGeNOxBMZZJvVmtx3TOK4vrk/uogD2VS+quUjQ5YSB3Eu3zxQj1NeyAqDM=" } }
- id (Message ID)
- 2009-02-01以前のAPIでは、メッセージを削除するときにこの値を指定していた。現在は、Receipt Handleの方を利用する。
- body
- メッセージ本文
- handle (Receipt Handle)
- メッセージの削除や、メッセージのvisibility timeoutの変更にこの値を利用する。
メッセージ投入側
キューにメッセージを詰める場合。実際に使う場合、投げる方も受け取る方もPHPであれば、配列でデータを作成して、serializeして投げる、受け取った側はunserializeして配列として処理する (マルチバイトを含む場合は、base64_encode/decodeも噛ませる) というのが、便利で汎用性も高いと思います。
<?php require 'Services/Amazon/SQS/Queue.php'; define('AMAZON_ACCESS_KEY', your access key); define('AMAZON_SECRET_ACCESSKEY', your secret access key); define('QUEUE_URL', 'http://queue.amazonaws.com/508403871985/test-queue'); $sqs = new Services_Amazon_SQS_Queue(QUEUE_URL, AMAZON_ACCESS_KEY, AMAZON_SECRET_ACCESSKEY); try { $sqs->send('this is new message!'); } catch (Services_Amazon_SQS_Exception $e) { // 失敗したらケアする trigger_error($e->getMessage()); }
メッセージ受信側
キューからメッセージを取得して、処理をするようなコマンドラインスクリプトの場合、こんな感じ。
<?php require 'Services/Amazon/SQS/Queue.php'; define('AMAZON_ACCESS_KEY', your access key); define('AMAZON_SECRET_ACCESSKEY', your secret access key); // queueのURIを指定 define('QUEUE_URL', 'http://queue.amazonaws.com/508403871985/test-queue'); $sqs = new Services_Amazon_SQS_Queue(QUEUE_URL, AMAZON_ACCESS_KEY, AMAZON_SECRET_ACCESSKEY); while(1) { // 1件だけ取得 list($item) = $sqs->receive(1); // ジョブがなければ10秒待ってリトライ if (empty($item)) { echo 'queue is empty!', PHP_EOL; sleep(10); continue; } echo 'item body is ', $item['body'], PHP_EOL; // ここで時間のかかる作業をやる // 必要に応じて、visibility timeoutを延長したりする $sqs->delete($item['handle']); echo 'item delete.', PHP_EOL; }