Amazon SQS による分散キュー

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon SQS とは

Amazon SQS は、AWSが提供する分散キューサービスです。APIを使ってアクセスすることができます。SQSによってアプリケーションのメイン処理と非同期に動いてほしい処理を分離することができます。キューは待ち行列を提供し生産者(Producer)によって生成されたメッセージのバッファリングをし、消費者(Consumer)によってコンポーネントへメッセージデータが渡されます。キューは複数登録することができます。キューに対して複数のリーダーとライターが接続できますので、ひとつのキューに対して複数のアプリケーションから同時に利用することができます。

分散キュー

SQSは障害時に正常系へ切り替わるように設計された(フェイルセーフな)仕組みを提供しています。おなじみの分散配置されたAWSインフラの成せる技です。キューの仕組みは自前でも構築は容易ですが、フェイルセーフであったりAPI接続を実現するためには多くの投資が必要です。SQSの仕組みはS3やSimpleDBと同じで、インフラ部分の管理をAWSに任せることができて非常に便利です。ただし、気をつけるべきポイントがあります。SQSはキューに登録されたメッセージが間違って消えてしまわないように分散コピーされます。トレードオフとして、順序は保証されません。また、キューに登録されたメッセージが2回取得される可能性があります。また、ある問い合わせでキューが空だったとしても空で無い可能性があります。いわゆる結果整合性を提供します。多くの場合うまく動いてしまって気付かないかもしれませんが、キュー内のメッセージで順序や単一実行を保証したい場合にはトランザクションの仕組みを提供しているサービスであるSimpleDB(ConsistentRead=true)やRDSと組み合わせる必要があります。結果整合性の特徴を理解し活用することで大規模な分散キューイング処理を安価に実現できるわけです。

メッセージの制限

SQSはキューの登録数に制限はありませんが、メッセージのサイズ制限はデフォルトで8KBです。サイズ制限を変更するにはMaximumMessageSizeパラメータを変更します。 1024 bytes (1KB)から65536 bytes (64KB)まで変更可能です。さらにこれ以上の情報を扱いたい場合にはS3やSimpleDBと組み合わせる必要があります。SQSはポインターとして使うのが良さそうですね。

SQSのAPI

Amazon SQSはキューを操作するAPIが提供されています。

  • CreateQueue:あなたのAWSアカウントで使用するキューを作成します。
  • ListQueues:既存のキューをリストアップします。
  • DeleteQueue:キューの1つを削除します。
  • SendMessage:データエントリを指定されたキューに追加します。
  • ReceiveMessage:指定されたキューから1つ以上のメッセージを返します。
  • ChangeMessageVisibility:以前に受け取ったメッセージの視認可能期間の期限を変更します。
  • DeleteMessage:指定されたキューから以前に受け取ったメッセージを削除します。
  • SetQueueAttributes:再度読み込まれないように読み込み後にメッセージがロックされる時間のような、キュー設定をコントロールします。
  • GetQueueAttributes:キューに含まれるメッセージ数のような、キューについての情報を参照します。
  • AddPermission:指定されたキューについて、別のAWSアカウントのために共有するキューを追加します。
  • RemovePermission:指定されたキューのために共有しているキューから、AWSアカウントを削除します。

メッセージのライフサイクル

キューに登録されたメッセージにはライフサイクルがあります。あるコンポーネントAからSendMessageによってキューに追加されたメッセージは、コンポーネントBからReceiveMessageによって取り出されます。このとき、他のコンポーネントCから何度も同じメッセージを取得しないように Visibility Timeout の期間だけ見えなくなります。この潜伏期間を過ぎると再度見えるようになります。キューからは消えません。キューからメッセージを削除するには、DeleteMessageによってメッセージを削除する必要があります。実際のシステムでは、コンポーネントBによって処理が正常終了した際にキューへメッセージの削除命令を出すような流れになると思います。

各メッセージのVisibility Timeout は、キューを新規作成するとき(CreateQueue)にDefaultVisibilityTimeoutパラメータによってキューごとにデフォルト値を変更することができます。何も設定しないときにはデフォルト値として30秒が設定されます。最大値は43200秒(12時間)です。メッセージごとに変更する場合には、メッセージ受信時(ReceiveMessage)に、VisibilityTimeoutパラメータによって設定可能です。ちなみに、キューに残ったメッセージは4日経過すると自動的に削除されます。この値は、MessageRetentionPeriodパラメータによって1時間から14日間まで変更可能です。

以下は、キューへのメッセージの追加・取得・削除の一般的な流れを表した図です。①でキューにメッセージAが登録します。この段階ではVisibility Timeoutは動きません。

次に②でキューからメッセージAを取り出します。このタイミングでVisibility Timeoutが動き出します。

最後に③でキューからメッセージAを削除しました。再度キューに現れることなくメッセージAは正常に終了したということが伺えます。

以上から、Visibility Timeoutの値は、消費者(Consumer)側の処理の最大時間以上を設定しておくことがよさそうですね。なぜならば、処理が終わる前に再度キュー内で表示されるようになってしまうと二重処理になる可能性があるためです。ここら辺は、未処理・処理中・完了のステータスをSimpleDBで行うのもアリかと思います。

まとめ

Amazon SQS は、安価に生産者(Producer)&消費者(Consumer)モデルのキューイングサービスを提供することが分かりました。また、キューやメッセージごとに生存期間や可視期間を柔軟に設定することができ、利用者のサービスの特性に合わせられることも分かりました。Amazon SQSの用法を理解して楽しく使いましょう~

参考ドキュメント

Amazon Simple Queue Service Developer Guide