こんにちは。青木です。
この投稿はF# Advent Calendar 2011の12/22エントリです。
←前回 @zecl F# Implementation of BackPropagation Neural Network for Pattern Recognition(LifeGame)
10月のイベントでMSとMVPの方にF#の良さを色々と教えてもらいました。
また、豆蔵の方から関数型言語の話を聞く機会が増えてきました。
そんなこともあり、関数型言語F#とMicrosoftのクラウドであるAzureを組み合わせたアプリケーション構築にチャレンジしてみました。
作成するアプリケーションの内容
作成するアプリケーションはWindows AzureのWorkerRoleです。WorkerRoleは、アプリケーションサーバー的な役割を果たします。
実装する処理は、AzureのQueueストレージにデータが存在すればメッセージを取り出し、その値をTableストレージに登録します。そして登録が終了すればQueueからメッセージを削除します。
それでは実装手順を見ていきましょう。
新しいプロジェクトの作成
まず、VisualStudio 2010を立ち上げ、新規のクラウドアプリケーションの作成を選択します。表示されたダイアログからF#のWorkerRoleを選択します。
OKを押すと、F#のWorkerRoleプロジェクトが作成されます。
生成されたプロジェクトとコード
次のようなプロジェクトが生成されます。
このままビルドすれば、開発環境で動作を確認することができます。
続けて、F#で処理を書いてみます。
OnStartメソッドに初期処理を追記
まず、OnStartメソッドに設定ファイル(ストレージ情報)を読み込むコードを記載します。
--------------------------------------------------------------- //設定ファイル用の処理 let envConfig configName (setter:Func<string, bool>) = let configValue = RoleEnvironment.GetConfigurationSettingValue(configName) setter.Invoke(configValue) |> ignore let act = new Action<string, Func<string, bool>>(envConfig) CloudStorageAccount.SetConfigurationSettingPublisher(act) ---------------------------------------------------------------
Entityクラスを定義
--------------------------------------------------------------- // TableストレージのEntity用のクラス type UserEntity() = inherit TableServiceEntity() do //コンストラクタで、親クラスのプロパティ呼び出し base.PartitionKey <- DateTime.UtcNow.ToString("yyyyMMdd") base.RowKey <- Guid.NewGuid().ToString() //名前を保存するプロパティ let mutable name = "" member this.Name with get () = name and set (value) = name <- value ---------------------------------------------------------------
Runメソッドにメイン処理を追記
最後にメイン処理のRunメソッドに、ストレージの準備、Queueを読み出す処理、Tableに登録する処理を記載します。
--------------------------------------------------------------- // Runメソッド override wr.Run() = log "WorkerRole1のエントリポイントが呼ばれました" "Information" // 設定ファイルの読み出し let storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString") // キュー let queueStorage = storageAccount.CreateCloudQueueClient() let queue = queueStorage.GetQueueReference("entry") // テーブル let tableStorage = storageAccount.CreateCloudTableClient() tableStorage.CreateTableIfNotExist("users") |> ignore let context = tableStorage.GetDataServiceContext() // メイン処理 while(true) do Thread.Sleep(10000) log "動作しています" "Information" // キューから取り出し let msg = queue.GetMessage() if msg <> null then // キューにメッセージがあれば取り出して、テーブルに保存 let entity = UserEntity() entity.Name <- msg.AsString context.AddObject("users", entity) context.SaveChanges() |> ignore queue.DeleteMessage(msg); log "1件処理しました" "Information" else log "データがありません" "Information" ---------------------------------------------------------------
実行
なお、ストレージ情報をDataConnectionStringの設定に記載しておく必要があります。
AzureStrageExploreでQueueに名前を入れたメッセージを登録すると、正しくTableにアイテムが登録されることがわかります。
最後に
今回は、C#で書くようなコードを、F#で書いてみました。
関数型言語に触れる目的でコーディングをしてみましたが、OOPに慣れているためか、手続き型で書いてしまいました。(正確には、いきなり関数型でコーディングしようとしても難しかったので、F#の構文を学ぶため、手続き型のC#のコード移植から踏み込んでみました。)
それでも、F#という言語には触れることができ、楽しく新しい刺激を受けることができました。
マルチサーバー・マルチコアで動作するWorkerRoleですので、今後は関数型言語のアプローチでプログラムを書いていきたいと思います。
サンプルコードのダウンロード(WokerRole.fs)
↑今回紹介したサンプルコードは上記のリンクからダウンロードできます。ZIPで圧縮しています。