2014年7月8日火曜日

AmazonSQSにMessageAttributeという機能が追加になっていたので試してみた

簡単に説明するとメッセージに対してメタ情報を付与できるサービスです
key - value 形式で属性を付与することができます
また value に対して型定義することができサーバ側で型のバリデーションを実施してくれます
どんな感じで使用できるのか試してみました

■環境
AmazonSQS
CentOS release 5.10 (Final)
クライアントツール java-signature

■試してみる
1. テスト用のキューを作成する
今回テストするためのキューを作成します
VisibilityTimeout は 0 で作成します

java -jar target/CallAws-jar-with-dependencies.jar -e sqs.ap-northeast-1.amazonaws.com -a CreateQueue -b '{"QueueName":"attributeTest","Attribute.1.Name":"VisibilityTimeout","Attribute.1.Value":0}' -u

2. まずはSendMessageしてみる
早速、Attributeを付与したMessageを送信してみます
Attributeは key - value 形式で登録でき、valueに型を指定することができます

以下のメッセージ情報を送信してみます
  • MessageBody・・・This is a test message
  • MessageAttribute・・・env
  • MessageValue・・・dev
  • MessageDataType・・・String
※QueueUrlに含まれるアカウントIDは念のため伏せております
java -jar target/CallAws-jar-with-dependencies.jar -e sqs.ap-northeast-1.amazonaws.com -a SendMessage -b '{"QueueUrl":"http://sqs.ap-northeast-1.amazonaws.com/xxxxxxxxxxxxxx/attributeTest","MessageAttribute.1.Name":"env","MessageAttribute.1.Value.StringValue":"dev","MessageAttribute.1.Value.DataType":"String","MessageBody":"This is a test message"}' -u
サンプルではAttributeは1つしか登録していませんが複数付与することも可能です
その場合は「MessageAttribute.1.Name」の「1」の部分を「2」にしてリクエストのボディに追加すればOKです
追加できる数に上限はありませんが、メッセージ全体で256KB以内でなければいけないという制約はあります

送信したメッセージをコンソールで見ると以下のような感じになります
※複数のAttributeが設定してある場合のイメージです


型はデフォルトで String, Number, Binary が提供されており型にあったValueが設定されていないとエラーとなります
Binary型の送信は試していませんが基本はプログラム上でメディアデータなどをbyte配列に変換し送信する感じかと思います
また独自の型を作成することもでき、その場合は「Number.int」「Binary.jpg」のように「.(ドット)」区切りで指定します

3. RendMessageで確認してみる
送信したメッセージを受信してみます
ReceiveMessage 時のリクエストに取得する MessageAttribute パラメータを指定します
「All」を指定するとメッセージに付与されているすべての Attribute 情報と MessageBody を取得することができます
Attribute には key の情報を指定するので今回は「env」と指定しています

java -jar target/CallAws-jar-with-dependencies.jar -e sqs.ap-northeast-1.amazonaws.com -a ReceiveMessage -b '{"QueueUrl":"http://sqs.ap-northeast-1.amazonaws.com/xxxxxxxxxxxxxx/attributeTest", "MessageAttributeName":"env"}' -u --format-xml

存在しない Attribute を指定するとエラーとはならず Attribute が含まれないレスポンスが返ってきます

レスポンスのサンプルを以下に記載します
<?xml version="1.0" encoding="UTF-8"?><ReceiveMessageResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/">
  <ReceiveMessageResult>
    <Message>
      <Body>This is a test message</Body>
      <MD5OfBody>fafb00f5732ab283681e124bf8747ed1</MD5OfBody>
      <ReceiptHandle>cOJv9qrD9XLVlpsfwYn3xbqoRwvfbdaQLvbKbLf00e/k6ciYz083Jqz15w+g0xpfpL3IZw32hD0mrLllzyQfgkZTT83Um5PLuE5qxjYeH6qhCZz6UBZXSD+J7ti4XbZYJ9qLk9EEoXffMmSogLbouqy4S/fiX6fnFxflHVcyItgHRtjk5TgDk6DJb831h7N2HtUohH/gWyI3d69S1Sc+RRYw++c0H50QatUG2T1GTqPxRDyb5jR6d6b1BiQXw2BV5u3qdGMF7re3RIQrx81kTlPLJIHHcmHa77JUGzBTldXwNNJotDOPSA==</ReceiptHandle>
      <MessageAttribute>
        <Name>env</Name>
        <Value>
          <DataType>String</DataType>
          <StringValue>dev</StringValue>
        </Value>
      </MessageAttribute>
      <MessageId>f3001768-2bd2-488e-8613-8fffaf66c410</MessageId>
      <MD5OfMessageAttributes>2c1856f51437cf57b1a473e4bee30521</MD5OfMessageAttributes>
    </Message>
  </ReceiveMessageResult>
  <ResponseMetadata>
    <RequestId>8184b4a6-f345-584e-a677-f8927c83f696</RequestId>
  </ResponseMetadata>
</ReceiveMessageResponse>
MessageAttribute タグ内に設定した Attribute 情報が付与されていることがわかります

■ユースケースを考える
とりあえず設定する方法と取得する方法はわかりましたが、では一体これはどんなときに使えるのでしょうか

Amazonの公式のBlogPostにもとしてユースケースが載っていました
この例だとモバイルアプリを想定しており、ガソリンの料金をシェアするアプリのようです
ガソリンの料金をシェアするみたいな感じで、アプリからメッセージを送信すると位置情報とガソリン料金が付与されたメッセージが送信されます
すると、サーバサイドでメッセージが受信されメッセージの Attribute に位置情報とガソリンの料金が入っていた場合に
その情報を AWS の DynamoDB に突っ込み、DynamoDB の GeoLibraryという機能を使うことで、そのガソリンスタンドの近くにいる人に最安のガソリンスタンドの情報をプッシュすることができるみたいなことを記載していました(間違っていたらすいません。。)

使い方はいろいろ考えられますが、メッセージがどんな属性なのかというのをメッセージ本文の情報とは別で管理できるので
メッセージを処理する、所謂ワーカー側は Attribute の情報だけをみて処理を判断することができます
また型も指定してあるので、取得した段階で必要な型にキャストされていることが保証されているのでワーカー側の実装も簡単になるのかなと思います

メッセージの Attribute 機能が実装される以前でもメッセージ本文にJSONなりなんなりでメタ情報を付与すれば同様のことすることはできるのかと思いますが
SQSの仕様として明確に「Attribute が key - value で指定できる」とすることでメッセージのデータ構造体というか作りが綺麗になるので
利用者からするとメッセージの管理がしやすくなるのかなと思います

最近は Backend As a Service といったモバイル向けのクラウドサービスも登場していることからその辺りを想定した機能を実装したのかもしれません
バイナリデータを指定できる部分とかはまさにモバイル向けなのかなと思いました

■参考URL

0 件のコメント:

コメントを投稿