こんにちは。サイオステクノロジー武井です。今回は、Azureで利用できる非同期処理のためのメッセージキューイングについてお話したいと思います。
非同期処理とは?
まず非同期処理について、説明します。ユーザー登録やメール送信処理を実現するための一般的なフローは以下の通りと思います。
- ユーザーがブラウザから情報を入力する
- Webアプリケーションは、入力した情報に基づき、ユーザー登録やメール送信処理などのを行う。
- ユーザーのブラウザに処理完了画面が表示される。
ユーザーは2の処理が完了して、完了画面が表示されるまで、待つことになります。しかし、一般的にユーザー登録やメール送信処理などは、ユーザーがその処理結果をすぐに必要なものではありません。
ユーザー登録したからと言って、すぐにそのユーザーが利用することはないと思います。ユーザーへのIDやパスワードの通知などの業務処理がありますから、ある程度処理が遅延しても構いません。極端なことを言えば、ユーザー登録処理を開始してから完了するまで、数時間かかっても、業務上支障がないケースはあります。メールにしても同じと思います。
すぐに結果が必要のない、遅延しても良い処理のために、ユーザーがそのレスポンスをずっとブラウザの前で待ち続けるのは時間のムダです。
そこで、非同期処理の出番になります。
今までの非同期処理
今までの非同期処理は、ユーザーからリクエストがあったら、別プロセスを起動させ、そのプロセスに別の処理を行わせるものでした。下記のようなフローになります。
この方法であれば、ユーザーの入力をWebアプリケーションが受け取ると、別のプロセスを起動して、そのプロセスに処理を任せるので、ユーザーにはすぐに完了画面を返すことができます。
しかし、この方法には最大の欠点があります。それは、ユーザーの入力があるたびにプロセスが起動するので、サーバーが高負荷になるという点です。昨今、サーバーリソースは全てクラウド上でまかなう風潮がありますが、あまりに高負荷となると、リソース増強を余儀なくされ、利用料金にも跳ね返って来ます。
そこで、最近の非同期処理は別の形を取っています。
最近の非同期処理
最近の非同期処理は、メッセージ・キューというものを利用します。Webアプリケーションはユーザーからの入力を受け取ると、そのままその情報をメッセージキューに格納します。
Webアプリケーションとは別のプロセスで、Workerプロセスというものが起動しており、常時キューを監視し、キューに情報が入ってきたら、順次処理をして、ユーザーに結果を返します。
この方法であれば、起動しているプロセスは常にWorkerプロセス1つですので、サーバーのリソースを浪費しません。また、Webアプリケーションが、キューを登録するのも一瞬で終わるので、ユーザーの待ち時間は短くなります。
Azureでの実現方法
メッセージキューを用いた非同期処理をAzureで実現する方法を記載します。
AzureにはAzure StorageキューとService Busキューの2種類あります。平たくいってしまえば、前者は機能は少ないけれど高速、後者は多機能だけど若干レスポンスが遅いかもといったところです。このあたりの説明は今回割愛します。
今回は、シンプルなAzure Storageキューでの実現方法を記載します。以下のような構成とします。
まず、キューを格納する入れ物がなければ話になりません。Azureポータルからその入れ物を作りましょう。
Azureポータルにログインして、左部メニューからSotrage accountsを選択して下さい。検索ボックスから探すと便利です。
「Name」にキュー名、「Account Kind」に「General Purpose」を選択して、「Create」をクリックして下さい。
Straogeアカウントのリストに、先程作成したアカウントが表示されますので、クリックして下さい。
「Queues」をクリックして下さい。
「+Queue」をクリックして下さい。
「Queue name」に任意の名前を入力して、「OK」をクリックして下さい。
左部メニューの「Access Key」をクリックして下さい。以下に表示される「Storage account name」「CONNECTION STRING」をメモしておいて下さい。
これでキューを入れる入れ物の準備は完了です。
次にWorkerプロセスを作成します。言語はJava、ビルドツールはMavenを使うことを前提とします。Java以外にもSDKは豊富にあります。
pom.xmlに以下を追記下さい。
<dependencies> <dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-storage</artifactId> <version>5.5.0</version> </dependency> </dependencies>
次にWorkerプロセス側です。以下のファイルを作成して下さい。そして実行して下さい。
public class Worker { public static final String storageConnectionString = "先程メモしたCONNECTION STRING"; public static void main(String[] args) { // CONNECTION STRINGの情報をもとにキューの入れ物に接続する CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString); // キューのクライアントを生成する CloudQueueClient queueClient = storageAccount.createCloudQueueClient(); // キュー名をセットする CloudQueue queue = queueClient.getQueueReference("先程メモしたキュー名"); // 無限ループによりキューを監視する while (true) { // キューからメッセージを取得する CloudQueueMessage retrievedMessage = queue.retrieveMessage(); if (retrievedMessage != null) { // メッセージを標準出力に表示する System.out.println(retrievedMessage.getMessageContentAsString()); // キューを削除する queue.deleteMessage(retrievedMessage); } } } }
次にクライアントを作成します。
public class Client { public static final String storageConnectionString = "先程メモしたCONNECTION STRING"; public static void main(String[] args) { // CONNECTION STRINGの情報をもとにキューの入れ物に接続する CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString); // キューのクライアントを生成する CloudQueueClient queueClient = storageAccount.createCloudQueueClient(); // キュー名をセットする CloudQueue queue = queueClient.getQueueReference("先程メモしたキュー名"); // キューを送信する CloudQueueMessage message1 = new CloudQueueMessage("Hello, World1"); queue.addMessage(message1); } }
Woerkプロセス側の標準出力に「Hello World」出力されるはずです。
以上が、Azureによるメッセージキューイングの方式です。