F#でWindows AzureのWorkerRoleを動かしてみる

こんにちは。青木です。

この投稿は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を選択します。

F#プロジェクト作成画面

OKを押すと、F#のWorkerRoleプロジェクトが作成されます。


生成されたプロジェクトとコード

次のようなプロジェクトが生成されます。
作成された状態のF#のプロジェクト

このままビルドすれば、開発環境で動作を確認することができます。
続けて、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ストレージで使うクラスを定義します。
F#は書いた順番に読みだされるので、WorkerRoleクラスの上にこのクラスを定義します。
本来は新しいF#ファイルを作ってソリューションエクスプローラでWorkerRoleファイルの上に持っていくべきですが、今回はてっとり早くWorkRoleクラスと同じファイルに記載しました。
--------------------------------------------------------------- 
// 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の設定に記載しておく必要があります。
azure-vs-fs

Visual Studioでデバッグ実行すると、ストレージのエミュレーターが起動します。実行ログが出力されていることが分かります。

Azureの実行状況

AzureStrageExploreでQueueに名前を入れたメッセージを登録すると、正しくTableにアイテムが登録されることがわかります。

Tableストレージに登録されたデータ

最後に

今回は、C#で書くようなコードを、F#で書いてみました。

関数型言語に触れる目的でコーディングをしてみましたが、OOPに慣れているためか、手続き型で書いてしまいました。(正確には、いきなり関数型でコーディングしようとしても難しかったので、F#の構文を学ぶため、手続き型のC#のコード移植から踏み込んでみました。)
それでも、F#という言語には触れることができ、楽しく新しい刺激を受けることができました。

マルチサーバー・マルチコアで動作するWorkerRoleですので、今後は関数型言語のアプローチでプログラムを書いていきたいと思います。

サンプルコードのダウンロード(WokerRole.fs)

WorkerRole

↑今回紹介したサンプルコードは上記のリンクからダウンロードできます。ZIPで圧縮しています。


ネクストスケープ企業サイトへ

NEXTSCAPE

検索する

タグ

メタデータ

投稿のRSS

著者

青木淳夫です。
.NETとアジャイルと散歩が好きなエンジニアです。
「aoki」さんの全ポストを読む