2011年6月22日水曜日

Amazon SQSってなんじゃ?(その1 Scratchpad編)

SimpleDBの回は途中で一休みして、SQSでも遊んでみました。
Amazon SQS(Simple Queue Service)は、AWSが提供するメッセージキューシステムです。
メッセージキューは、送信側と受信側が別のプロセスで非同期にメッセージのやりとりを行い、送信と受信の間でお互いの処理待ちをなくすことのできる仕組みをもっています。
これはたとえばWEBアプリケーションなどで、画像生成などの重い処理をするときに処理のタスクだけを指示して、レスポンスをすぐ返すことによりクライアントに処理待機をさせないようにするときなどに有用です。

SQSではメッセージの送信、受信側での処理は以下のような流れになります。
使い方はとてもシンプルで、送信側でメッセージを送り、受信側でメッセージの受信を待機するだけです。

送信側
  1. 指定したキュー名のキューオブジェクトを作る
  2. メッセージを送る

受信側
  1. 指定したキュー名のキューオブジェクトを作る
  2. メッセージの待機
  3. メッセージを受け取ったら処理
  4. メッセージを削除

さっそく利用してみます。
まずSQSのページで利用申し込みします。

申し込むと登録完了メールが届いて、すぐつかえるようになります。

このSQSにもscratchpadというJavascriptで書かれたツールがあるので、使用してみます。
Javascript Scratchpad for Amazon SQSをダウンロードし、解凍したフォルダのindex.htmlをブラウザで開きます。

ヘッダにアクセスキーとシークレットアクセスキーを入力して、右側のリストから仕様したいAPIを選びます。

キューの作成

まず送信側の処理に必要なキューの作成をします。右側のAPIリストから"CreateQueue"を選択します。


パラメータは以下のとおりです。
  • QueueName(必須):キュー名。SQSではキューはラジオのチャンネルのようなもので自分が使用するSQSインスタンスの中でユニークである必要があります。あるキュー名を指定するといつでも同じキューが取得でき、同じキューに対してメッセージの送受信を行います。
  • Default Visibility Timeout(オプション):受信側クライアントのインスタンスが複数ある場合、1つのインスタンスがメッセージを受信するとここで指定した時間(秒)の間は、他のインスタンスからは隠されます。それによってその間重複することなく受信処理を完了することができます。デフォルトは30秒で、非常に重い処理をする場合はこの秒数を多くします。

ここではQueueNameに"hoge"と入力し、Invoke Requestを押します。
すると、以下のようなレスポンスが返ります。
<CreateQueueResponse>
  <CreateQueueResult>
    <QueueUrl>https://queue.amazonaws.com/821635308497/hoge</QueueUrl>
      </CreateQueueResult>
    <ResponseMetadata>
    <RequestId>e490c631-b519-4e02-a610-55ab66b2fac2</RequestId>
  </ResponseMetadata>
</CreateQueueResponse>
ここでQueueURLというのが"hoge"というキューにアクセスするための識別子になります。このURLはキュー名に対し一意なもので、送信するときも受信するときにもこのURLを指定してメッセージのやりとりを行います。CreateQueueを何度行ってもキュー名が同じならばURLは同じものになります。つまりCreateQueueというのはキューをいくつもつくるのではなく、与えたキュー名から一意なキューURLを取得する処理だといえます。これは76.1MHzにあわせれば毎回interfmにつながるのと同じです。

メッセージの送信

次はメッセージの送信です。ヘッダのAPIリストから"SendMessage"を選択します。
パラメータは以下の2つです。
Queue Url(必須)::キューの作成で取得したキューURLを指定します。メッセージはこのURLをキューの識別子として送信され、受信側でもこのURLを指定して受信します。
Message Body(必須):メッセージの内容です。

ここではQueueUrlに先ほど作成した"hoge"というQueueのQueuUrl "
https://queue.amazonaws.com/821635308497/hoge"を、MessageBodyには"Hello World!"を入力してInvoke Requestを押します。
すると以下のようなレスポンスが返ります
<SendMessageResponse>
  <SendMessageResult>
    <MD5OfMessageBody>ed076287532e86365e841e92bfc50d8c</MD5OfMessageBody>
    <MessageId>f5735801-1b32-44f6-a86b-416a04bb969a</MessageId>
  </SendMessageResult>
  <ResponseMetadata>
    <RequestId>233b5572-e2a6-4e30-8ee3-27250276168f</RequestId>
  </ResponseMetadata>
</SendMessageResponse>
これでメッセージがキューに送られました。

メッセージの受信

次にメッセージを受信してみます。
APIリストから"ReceiveMessage"を選びます。


パラメータが以下のとおりです。
  • QueueUrl(必須):送信時と同じキュー名に該当するキューURLを指定します。CreateQueueで取得します。
  • Max Number Of Messages(オプション):取得する最大のメッセージ件数を指定します。デフォルトは1です。一度にたくさんのメッセージを処理したい場合はこれを増やします。
  • Visibility Timeout(オプション):一度メッセージを受信するとこの秒数の間は、他のインスタンスのReceiveMessageリクエストからこのメッセージを隠します。デフォルトはキューのVisibility Timeoutと同じになります。
 ここではQueueUrlに先ほどの送信時のキューURL"https://queue.amazonaws.com/821635308497/hoge"を指定して、InvokeRequestを押すと以下のレスポンスが返ります。
<ReceiveMessageResponse>
  <ReceiveMessageResult>
    <Message>
      <MessageId>f5735801-1b32-44f6-a86b-416a04bb969a</MessageId>
      <ReceiptHandle>0NNAq8PwvXtwwfdMtBtd6ZxXkxF39Z/IYeGA072QQSZ0DJ3gVOmjI2Gh/oFnb0IeJqy5Zc8kH4JARkzdFBpldzaAPSeOkXQZwFSsJUhd5VMVLzK3+eRCyfzyRC5taEby2sLs6d2PAFOgJcNQRNWCRx2ZBrIVvHrDEKIvb6EDD5Mzd5Tn7Sx1Kdc/TnR7K9fu</ReceiptHandle>
      <MD5OfBody>ed076287532e86365e841e92bfc50d8c</MD5OfBody>
      <Body>Hello World!</Body>
    </Message>
  </ReceiveMessageResult>
    <ResponseMetadata>
      <RequestId>5115c13c-5c58-4f35-aae0-505c892a9c00</RequestId>
    </ResponseMetadata>
</ReceiveMessageResponse> 
ここで、ReceiveMessageResultの中にMessage要素が含まれており、その中のBody要素に先ほど送信した"Hello World!"が確認できます。このBody要素がメッセージ本体になります。
また、 Message要素の中のReceptHandleはメッセージの削除に使用されます。

メッセージの削除

メッセージは受信しただけでは削除されません。
通常メッセージは受信した後に明示的に削除する必要があります。
APIリストからDeleteMessageを選択します。


パラメータは以下の2つです。
Queue Url(必須):削除したいメッセージが含まれているキューのURLです。送信や受信時のキューURLと同じものです。
Recept Handle(必須):受信したメッセージに含まれるReceptHandleを指定します。これはそのキューの中のメッセージへのポインタのようなものです。

QueueUrlに受信時のキューURLとして指定したのと同じ"https://queue.amazonaws.com/821635308497/hoge"、Recept Handleに受信のレスポンスに含まれていたReceptHandleである"0NNAq8PwvXtwwfdMtBtd6ZxXkxF39Z/IYeGA072QQSZ0DJ3gVOmjI2Gh/oFnb0IeJqy5Zc8kH4JARkzdFBpldzaAPSeOkXQZwFSsJUhd5VMVLzK3+eRCyfzyRC5taEby2sLs6d2PAFOgJcNQRNWCRx2ZBrIVvHrDEKIvb6EDD5Mzd5Tn7Sx1Kdc/TnR7K9fu"を指定して、Invoke Requestを押します。

すると以下のレスポンスが返り、メッセージが削除されます。
<DeleteMessageResponse>
  <ResponseMetadata>
    <RequestId>bb6333a8-bc6f-4151-ace4-efbca103316d</RequestId>
  </ResponseMetadata>
</DeleteMessageResponse>

他にもいくつかAPIが存在しますが、通常メインで使用するのは、上記の4つになります。
次回はこれをプログラムから使用してみます。