(10)Workerロールを実装する その1-コンテナとキューの作成
それでは次に、Workerロールを実装していきましょう。
最初の手順として、コンテナとキューを作成するコードを、「WorkerRole1」プロジェクト内のWorkerRole.csに次のリスト5のように記述します。
// … 前略 … using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.ServiceRuntime; // 追加したusingディレクティブ *1 using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; namespace WorkerRole1 { public class WorkerRole : RoleEntryPoint { public override void Run() { // ストレージアカウントの取得 *2 string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); // ブロブとキュークライアントの作成 *3 CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // オリジナル画像用コンテナの作成(存在しなければ) *4 CloudBlobContainer imagesContainer = blobClient.GetContainerReference("images"); imagesContainer.CreateIfNotExist(); // コンテナの公開アクセスの許可レベルを、コンテナに設定 *5 BlobContainerPermissions permissions = imagesContainer.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; imagesContainer.SetPermissions(permissions); // サムネイル画像用コンテナの作成(存在しなければ) *6 CloudBlobContainer thumnailsContainer = blobClient.GetContainerReference("thumnails"); thumnailsContainer.CreateIfNotExist(); // コンテナの公開アクセスの許可レベルを、コンテナに設定 *7 permissions = thumnailsContainer.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; thumnailsContainer.SetPermissions(permissions); // キューの作成(存在しなければ) *8 CloudQueue queue = queueClient.GetQueueReference("createthumnails"); queue.CreateIfNotExist(); // … 以下、手順[11]で説明するので省略 … } // … 以下、省略 … } }
リスト中のRunメソッドは、自動生成されたWorkerRole.csの中で、その雛形が定義されています。デフォルトでは次のリスト6のようになっており、開発者はこのメソッド中にキューからメッセージを取り出し処理するコードを記述していきます。
public override void Run() { // This is a sample worker implementation. Replace with your logic. Trace.WriteLine("WorkerRole1 entry point called", "Information"); while (true) { Thread.Sleep(10000); Trace.WriteLine("Working", "Information"); } }
リスト5の説明に話を戻します。WorkerRole.csには、デフォルトでMicrosoft.WindowsAzure.DiagnosticsとMicrosoft.WindowsAzure.ServiceRuntimeの2つのusingディレクティブが記述されています。それに追加する形で、Windows Azureマネージライブラリの2つのusingディレクティブを追加します(*1)。
*2~*8のコードについては、手順(7)で、WebロールのDefault.aspx.csに記述したコードと全く同じものです。WebロールとWorkerロールは非同期で動作しているので、先に実行されたコードによって、両ロールで使用するコンテナとキューが作成されることになります。あくまでサンプルにおける、便宜的なコードとお考えください。
(11)Workerロールを実装する その2-メッセージの処理
Workerロール実装の次の手順として、同じWorkerRole.csのRunメソッドに、メッセージを処理するコードを次のリスト7のように追加します。
public override void Run() { // … 手順[10]で説明した部分なので省略 … while (true) { try { // メッセージの取得 *9 CloudQueueMessage message = queue.GetMessage(); if (message != null) { // メッセージ内容(ブロブ名)の取得 string blobName = message.AsString; Trace.TraceInformation(string.Format("メッセージの取得: message = '{0}'", blobName)); // オリジナル画像のダウンロード *10 MemoryStream orginStream = new MemoryStream(); CloudBlob orginBlob = imagesContainer.GetBlobReference(blobName); orginBlob.DownloadToStream(orginStream); // サムネイル画像の作成 *11 string option = blobName[blobName.Length - 1].ToString(); Stream thumbStream = CreateThumbnail(orginStream, option); // サムネイル画像のアップロード *12 CloudBlob thumbnailBlob = thumnailsContainer.GetBlobReference(blobName); thumbnailBlob.UploadFromStream(thumbStream); orginStream.Close(); thumbStream.Close(); Trace.TraceInformation(string.Format("メッセージの処理: message = '{0}'", blobName)); // メッセージの削除 *13 queue.DeleteMessage(message); Trace.TraceInformation(string.Format("メッセージの削除: message = '{0}'", blobName)); } else { // 1秒間待機 *14 Thread.Sleep(1000); } } catch (Exception ex) { // 例外発生時は、5秒間待機 *15 // その後、失敗したメッセージを再度処理する Thread.Sleep(5000); Trace.TraceError(string.Format("メッセージで例外発生: message = '{0}'", ex.Message)); } } }
まず、キューからメッセージを取得します(*9)。
メッセージが存在すれば、メッセージ内容を元に(これはオリジナル画像URIを意味しているので)ブロブからオリジナル画像をダウンロードします(*10)。
次に、ダウンロードしたオリジナル画像と、メッセージ内容の最後に付加されているサムネイル画像作成時のオプション指定の情報を元に、サムネイル画像を作成します(*11)。このCreateThumbnailメソッドの実装については、次の手順で扱います。
次に、作成したサムネイル画像をブロブにアップロードします(*12)。
最後に、処理を終了したメッセージを削除します(*13)。処理が終わったメッセージを明示的に削除しないと、いつまでもキューに残り続けるので注意してください。
キューにメッセージが存在しなかった場合には、1秒間待機します(*14)。
*9~*14までの一連の処理が、while(true)のステートメントにより、ずっと繰り返されます。何かの理由で例外が発生した場合でも、キューにはメッセージが残っているので、しばらく待機した後、そのメッセージが再び処理されます。
なお、Workerロールはユーザーインターフェースを持ちませんので、実行状況の確認やデバッグ時の助けとして、System.Diagnostics.Traceクラスを使用してトレース情報を出力しています。開発環境では、Windows Azureのシミュレーション環境であるDevelopment Fabricを使用して、トレース情報を確認できます。