先日の Windows Azure Web サイトのアップデートで管理ポータルから WebJobs の追加が可能になったので、Kudu の API を叩いたりしなくても簡単に登録できるようになりました。
詳しくは抱かれたい男 No.1 ことかめぶちさんのブログを見ると、詳しく解説されているのでおススメです。
Windows Azure WebサイトのWeb Jobs (Preview) « ブチザッキ
しかし、No.1 が頑張って書いた後に、WebJobs を簡単に実装したり確認したりできる Windows Azure WebJobs SDK のプレビューをリリースした ASP.NET チームはマジで鬼畜でした。
WebJobs SDK の使い方ドキュメントは ASP.NET 公式サイトにて公開されていますし、SDK 本体は NuGet から簡単にインストールできます。
Get Started with the Azure WebJobs SDK
Hanselman 氏のブログでも早速紹介されていますね。
Introducing Windows Azure WebJobs - Scott Hanselman
そして WebJobs SDK をインストールして一通り試してみたところ、いい感じにストレージ周り(Blob, Queue, Table)が属性で使いやすくなっていて、実際のアプリケーションのバッチで必要な処理を簡単に実装出来そうです。
既に公式ドキュメントや Hanselman 氏のブログで紹介されていますが、ストレージ用の属性周りに注目して書いていきます。
準備する
まずは WebJobs SDK のインストールですが、コンソールプロジェクトを作成して NuGet で以下のパッケージをインストールするだけとなっています。
NuGet Gallery | Microsoft.WindowsAzure.Jobs.Host 0.1.0-alpha1
Install-Package Microsoft.WindowsAzure.Jobs.Host -Pre
非常にお手軽ですね。
後はローカル実行する場合には App.config に以下の接続文字列を追加しておきます。いたって普通のストレージアクセス用接続文字列です。
<connectionStrings> <add name="AzureJobsRuntime" connectionString="DefaultEndpointsProtocol=https;AccountName=XXXX;AccountKey=XXXXX"/> <add name="AzureJobsData" connectionString="DefaultEndpointsProtocol=https;AccountName=XXXX;AccountKey=XXXXX"/> </connectionStrings>
さて、これで WebJobs SDK を使う準備が出来たので、実際に属性を詳しく見ていきましょう。
Blob
Blob の操作用には BlobInput / BlobOutput 属性が用意されています。名前からわかるように入力と出力で分かれていて、メソッドのパラメータ属性として付けるようになっています。
コンストラクタの引数でターゲットとなる Blob のパスを指定しますが、{name} のように括るとパターンマッチになるみたいです。このあたりの挙動はドキュメントを待ちたいですね。
そして対応している型は以下のようになっています。
- Stream
- TextReader / TextWriter
- string / out string
- CloudBlob / ICloudBlob
- CloudPageBlob / CloudBlockBlob
例えば、以下のようなメソッドを用意すると、container という名前のコンテナ以下に格納された Blob を string として取得できます。
public static void ReadNewBlob([BlobInput("container/{name}")] string contents) { }
ちなみにこのメソッドが呼び出されるタイミングは新しく Blob が追加された時です。しかし、Blob の場合は 10 分間隔でチェックを行っているみたいなので、リアルタイムに近い処理を行いたい場合にはキューを使う方が良いみたいです。
サンプル用に Blob にアップロードされた画像を半分にリサイズするメソッドを実装してみました。
public static void SaveThumbnail([BlobInput("original/{name}")] Stream input, [BlobOutput("thumbnail/{name}")] Stream output) { using (var original = new Bitmap(input)) using (var thumbnail = new Bitmap(original.Width / 2, original.Height / 2)) using (var g = Graphics.FromImage(thumbnail)) { g.DrawImage(original, 0, 0, thumbnail.Width, thumbnail.Height); thumbnail.Save(output, original.RawFormat); } }
見た目は普通のメソッドですが、ちゃんとリサイズを行ってくれます。
ASP.NET では System.Drawing を使わない方が良いと言われているので、WebJobs に処理を投げてしまうのは便利そうです。
Queue
Queue の操作用には Blob の時と同様に QueueInput / QueueOutput 属性が用意されています。
コンストラクタ引数で対象のキューの名前を指定し、引数の型でキューで扱うメッセージの型を決定します。使える型は以下の通りです。
- string / out string
- object / out object
- byte / out byte
out はキューへメッセージを追加する場合には必要となります。複数のメッセージをキューに追加したい場合にはコレクション型を使えば良いみたいですね。
とりあえず簡単にキューからキューへメッセージを受け流すコードを書いてみました。
public static void QueueInout([QueueInput("queue1")] string input, [QueueOutput("queue2")] out string output) { output = "hello, " + input; }
実際にはメール送信など、少し時間がかかっても問題ないようなタスクを行う時に使うと非常に良さそうです。BlobOutput と組み合わせて、Blob への書き出し処理が完了したら完了キューに積むといった処理も簡単に実装出来そうですね。
Table
最後に Table ですが、これが結構異色となっています。コンストラクタ引数で対象のテーブル名を指定するのは他とあまり変わりませんが、属性は 1 つしか用意されていません。
そして指定できる型は以下の 2 つです。
- IDictionary<Tuple<string, string>, object>
- IDictionary<Tuple<string, string>, UserDefinedType>
Table ストレージを知っている人なら、この型がテーブルを直接表していることがわかると思います。キーに Tuple<string, string> を使っているのは PartitionKey と RowKey を表現するためですね。
public static void QueueToTable([QueueInput("sample")] string message, [Table("sample")] IDictionary<Tuple<string, string>, object> table) { table.Add(Tuple.Create("partitionKey", "rowKey"), new { Message = message }); }
ちなみにこのコードを実行すると、Table へは以下のようなデータが格納されます。
割とこのインターフェースは使いやすい気がしました。
ダッシュボードで確認
一通り実装を行ったので、実際に Web サイト上で動かしてみます。と言っても、登録周りは No.1 のブログなどで何回も説明されているので省略します。
とりあえず、実際にアップロードを行って WebJobs 用のダッシュボードを見ると、作成したメソッドが一覧表示されています。
既にテストで何回か試していたので、実行ログが右側に表示されていますね。成功・失敗したのかどうか、一目で分かるようになっているのもポイント高いですね。
メソッド名を選択すると、そのジョブの実行した時の情報が色々と見れるようになっています。
割とめんどくさいログ周りが標準で使えるようになっているのは便利すぎです。
クラウドサービスのワーカーロールに近いですが、ワーカーロールでは自前で実装する必要があった部分が PaaS 化された感じですね。また 1 つクラウドサービスを使う理由が無くなり、また 1 つ Web サイトが好きな理由が増えました。