こんにちは。大橋です。
今日はAmazon SQSについてです。
サイトを運営していると、ときどきメッセージキューで非同期に
処理をしたいなという箇所がよくあります。
また、最近、当社ではセールスフォースとAmazon EC2の併用など、異なる
クラウド環境を使ったシステムをを扱っており、その連携方法を日々調査しています。
1箇所のサーバ環境だけならば、GearmanやQ4Mなど自前インストール型のキュー
使えばよいかと思うのですが、クラウド環境間の連携などを考えると、
グローバルに利用できるメッセージ伝達方式の方が望ましいケースもあります。
そこで、今回Amazon SQSに触手を伸ばし、入門してみました。
今日は、その記録を残します。
【Amazon SQSを利用開始する】
Amazon Web サービスのアカウントにサインアップし、
Amazon SQSのページで「Amazon SQSの利用を申し込む」
をすればOKです。
【料金はすごく安い】
課金はリクエスト数によるものととデータ転送量によるものの2系統です。
リクエスト課金は 10,000回のAmazon SQSリクエストに付き0.01ドル。
ほとんどお金かかりません。
データ転送量は米国&欧州とアジア(シンガポール)で異なりますが、
たとえば、米国&欧州では10TB(テラバイト!!)までのデータ受信で
0.15ドル。同一RegionでEC2と送受信するものは課金されません。
すごくすごく気軽に使える値段です。(個人で利用しても気にならない価格です)
【少ないAPIで使えるシンプルな設計】
機能が少ないともいえますが、シンプルに使えます。
だいたいのことはには、以下の4つを使ってできます。
(1) CreateQueue : メッセージキューを作成する
(2) SendMessage : メッセージキューにメッセージを送信
(3) ReceiveMessage : メッセージキューからメッセージを受信
(4) DeleteMessage : メッセージキューからメッセージを削除
もちろん、他にもAPIはいろいろありますが、ちょっと試すだけならば
これでOKです。
キューを作成したあと、以下の絵のような流れで処理をすることになります。
Amazon SQSではメッセージは8192バイトが最大なので、もし大きなデータを
渡したい場合はAmazon S3やAmazon SimpleDBなど外部のデータストアに置いて
おき、そのポインタをメッセージに入れるのがよいです。
【メッセージ保存期間と視認性について】
メッセージは4日間、キューに保存されます。
また、あるクライアントがReceiveMessageしたあとは、他のクライアントは一定期間、
同一のメッセージが見えなくなります。
見えなくなる時間(視認できなくなる時間)はAPI経由で設定でき、30秒から12時間まで
設定できます。
もしAというクライアントがメッセージαを取得したあと、なにかしらの処理に
失敗した場合、メッセージαは、一定期間(30秒~12時間)のあとに、他のクライアントから
見えるようになります。
もちろん、そのAというクライアントが処理に成功し、メッセージ削除APIを
キューに対して呼び出した場合は、その後、他のクライアントから見えなくなります。
【使い方 ~Perlで実際に使ってみる~】
PHP編やJava編はいずれ機会があったら書きます。
とりあえず、Perlから使ってみます。
先ほどの絵でいうところのSendMessageする側(Process1)が「メッセージ送信側」、ReceiveMessageする側が「メッセージ受信側」(Process2)とします。
やりとりするメッセージはサンプルなので「Hello, World」とします。
メッセージ送信側がキューに対して'Hello, World'とメッセージをいれ、
メッセージ受信側はそのメッセージをキューから取得、画面に表示して
キューからメッセージを削除しています。
実運用ではメッセージは処理を依頼する内容やデータのポインタになります。
また、メッセージ受信側では、時間がかかる処理をするなど、なにかしらの
処理をします。
なお、Perlから使うにはモジュールのインストールが必要です。Amazon::SQS::SimpleというモジュールがCPANにありますので、サンプルプログラムを使うには以下のモジュールをインストールしてから実行する必要があります。
以下、サンプルプログラムです。
・メッセージ送信側
#!/usr/bin/env perl # sqs_msg_sender.pl use strict; use warnings; use Amazon::SQS::Simple; my $access_key = $ENV{AWS_ACCESS_KEY}; my $secret_key = $ENV{AWS_SECRET_KEY}; # SQSオブジェクトを作成します。 my $sqs = new Amazon::SQS::Simple( $access_key, $secret_key ); # キューを作成します。作成済みの場合に実行してもそのままキューがある状態になります。 my $q = $sqs->CreateQueue('sample_flect_queue'); # キューにメッセージを送付します。 $q->SendMessage('Hello World'); exit 0;
・メッセージ受信側
#!/usr/bin/env perl # sqs_msg_receiver.pl use strict; use warnings; use Amazon::SQS::Simple; my $access_key = $ENV{AWS_ACCESS_KEY}; my $secret_key = $ENV{AWS_SECRET_KEY}; # SQSオブジェクトを作成します。 my $sqs = new Amazon::SQS::Simple( $access_key, $secret_key ); # キューオブジェクトを取得します。 my $q = $sqs->CreateQueue('sample_flect_queue'); # キューからメッセージを取得します。 my $msg = $q->ReceiveMessage(); # メッセージの内容を出力してみます。 print $msg->MessageId() . "\n"; print $msg->MessageBody() . "\n"; # キューからメッセージを削除します。ReceiptHandleというのを使います。 $q->DeleteMessage( $msg->ReceiptHandle() ); exit 0;
【すぐに使えて高い信頼性があることについて】
メッセージキューは機能は非常にシンプルですが、同じようなキューを
自前で構築して、Amazon SQS並みの信頼性を保とうと思うとけっこう大変です。
たとえば、Q4MのようにMySQLを使うタイプのメッセージキューを自前で
構築した場合、1台くらいサーバが落ちてもメッセージをロストすることなく、
なおかつ、クライアントからのメッセージ送受信のリクエストをさばきつづける、
となると、必要な構築コストはかなり大きいです。
複数台のサーバが必要で、MySQLのレプリケーションをしたり、あるいは
DRBDで複数台のデータを同期させたり・・・、とかとか。ちょっと手間がかかりますね。
その点、Amazon SQSはAmazonが複数のサーバやデータセンターで冗長化していて大量のリクエストが来ても、ちゃんと止まらずにさばいてくれます。
そういったメッセージキューシステムを自前で作らなくても
すぐに本番システムレベルの信頼性で使える、というのは場合によっては
大幅なコスト削減になるんではないかと思います。
もちろん、パフォーマンス面など適合しないケースもあるかと思いますが、
クラウドな環境ではひとつの選択肢になるのではないかと考えています。
【制限や注意事項もあります】
基本的な注意事項は「メッセージ保存期間と視認性について」のところで
書いたとおりのこと、それと、メッセージが8192バイトが最大なので、
大きいデータの受け渡しが必要なときはS3などにデータをおき、その
ポインタ情報(URL)をやりとりするように、ということがあります。
その他に重要なポイントとしては
(1) 同一のメッセージが複数回受信できてしまうことがある。
(2) メッセージはキューに入れた順番どおりには受信できない。
ということです。
これはAmazon SQSが複数のサーバや複数のデータセンターを使って
運営されているためのようですが、注意が必要です。
(1)については場合によっては、Amazon SQS以外のデータストア
(Amazon SimpleDBなど)にどこまでのメッセージ処理ができたか、
などの情報を持っておく必要があります。
その辺はシステムの要求などによりケースバイケースだと思いますが、注意が必要です。
【まとめ&今後取り組むこと】
初期調査、入門だけなのに、記事が少しながくなってしまったので、今日は
これくらいにしておきます。
現在、私が行っているAmazon SQSの調査の最終ゴールは当社が現在力を入れている
Saleforceのシステムと連携させてみることです。
ちゃんと連携できたらまた記事にしますので、待っていてください。
なお、当社はAmazon Web Servicesに力を入れると同時に、Salesforce事業も
展開中です。現在、こういったいろいろなクラウドプラットフォームを使って
お客様によいソリューションを提供したい、というエンジニアの方を
大募集中です。もし、興味のある方は以下からご連絡いただけると幸いです。