Azure Web ジョブでバッチを実行する

Azure Web ジョブでバッチを実行するための簡易的な作業手順と、タイムアウトなどの注意点について記述します。

まず、Azure Web ジョブを配置するまでの基本的な流れは次の通りです。

  • ストレージを作成する
  • Web App を作成する
  • Web ジョブを開発して配置する

これらについて、以下に詳細を書いていきます。

■ ストレージを作成する

Azure ポータルで、ストレージを 1 つ作成します。
厳密には、

  • ログを格納するためのストレージ (AzureWebJobsDashboard)
  • バッチが利用するストレージ (AzureWebJobsStorage)

の 2 種類なのですが、1 つのストレージに両方の役割を持たせてもかまいません。
また、後の手順で接続文字列を使うため、[キー] からコピーしておきます。

■ Web App を作成する

Azure のポータルで、Web App を作成します。
[アプリケーション設定] の [接続文字列] で、「AzureWebJobsDashboard」をキーとする設定を追加します。
これで、WebJobs ダッシュボードを利用できるようになります。

接続文字列

 

■ Web ジョブを開発して配置する

Visual Studio で、新規のプロジェクトを [Azure WebJob] のテンプレートから作成します。
App.config を開くと、接続文字列の設定が 2 種類あります。
この両方に、先ほどと同じ接続文字列を設定します。

接続文字列

以下、Web ジョブの開発の流れを簡単に書いておきます。
なお、今回作成したサンプルは TaskWebJob (GitHub) にあります。バッチ処理の題材として、素数を求めています

(1) 手動またはスケジュールで開始する場合
詳細は Web ジョブ SDK を使用して Azure テーブル ストレージを使用する方法などを参照。

  • メソッドに [NoAutomaticTrigger] を付ける
  • JobHost.Call メソッドで、そのメソッドを呼び出す
  • Azure WebJob として発行する
    • オンデマンド実行またはスケジュール実行を選択する
  • 実行するには、ポータルの Web App の [Web ジョブ] で実行する

(2) キューをトリガーとして開始する場合
詳細は Web ジョブ SDK を使用して Azure キュー ストレージを操作する方法などを参照。

  • メソッドの引数に [QueueTrigger] を付ける
  • JobHost.RunAndBlock メソッドを使う
  • Azure WebJob として発行する
    • 連続実行を選択する
  • 実行するには、指定したキューにメッセージを追加する
    • 引数を渡すこともできる

 

以上で、Azure Web ジョブにバッチを配置することができました。
さて、バッチを実際に実行してみると、タイムアウトしてしまうことがあります。
以下では、タイムアウトについて書いていきます。

■ 有料プランの場合

既定では Web App の [アプリケーション設定] の [常時接続] がオフに設定されており、
Web App (というより Kudu?) が 20 分ほどでタイムアウトしてしまいます。
[常時接続] をオンに設定すれば解決します。

■ 無料プランの場合

無料プランでは、[常時接続] をオンにできません。
バッチの実行がタイムアウトする原因は 2 つあります。

  • Web App のタイムアウト
    • タイムアウトは 20 分ほどです。
    • Kudu への要求が連続的にされていれば、タイムアウトは延長されます。
  • CPU 時間の制限
    • 実際の時間ではなく、CPU を使用した時間です。
    • 例えば、連続して 3 分使うと、Web App が停止します。

したがって、WebJobs ダッシュボードなどを表示したままにして、
かつ CPU 使用率の低いバッチであれば実行可能ということになります。

そこで、例えば Thread.Sleep メソッドをコードに含めるという方法があります。
Thread.Sleep などでスレッドを中断しながら実行すると、CPU 利用率を激減させることができます。

CPU 時間の使用量は [クォータ] で見ることができます。

クォータ

 

作成したサンプル
TaskWebJob (GitHub)

参照
Azure Web ジョブのリソース
Azure App Service に .NET Web ジョブを作成する
Web ジョブ SDK を使用して Azure キュー ストレージを操作する方法
Web ジョブ SDK を使用して Azure テーブル ストレージを使用する方法
Web ジョブでバックグラウンド タスクを実行する
Visual Studio を使用して Web ジョブを展開する

LINQ で素数を求める (C#)

カテゴリー: クラウド. タグ: , . Leave a Comment »

Azure Web App をファイル サーバーとして使う

Azure Web App を、単にファイルを置く場所として使う方法について書いていきます。
基本的には Web App を作成するだけですが、フォルダーやファイルの一覧を表示する機能についても紹介します。

Azure のダッシュボードで [App Service] の [Web App] を作成します。

image

Web App が作成されると、https://xxx.azurewebsites.net の形式の URL でサイトにアクセスできるようになります。

image

作成した Web App で [ツール] – [Visual Studio Online (プレビュー)] を表示し、[オン] に切り替えます。

image

[移動] をクリックすると、Visual Studio Online "Monaco" が表示されます。

image

基本的な設定はこれでもう終了で、
あとはこの画面の [wwwroot] の下にフォルダーやファイルを追加していくだけです。
PC 上のファイルをドラッグ アンド ドロップしても追加できます。
テキスト ファイルであれば直接編集できます。

例えば [wwwroot] の下に test.txt を置いたとすると、
https://xxx.azurewebsites.net/test.txt の URL でファイルにアクセスできます。

 

以下は、フォルダーやファイルの一覧を表示するための手順です。

まず、[wwwroot] の下の hostingstart.html を削除します。
次に [wwwroot] の下に [Web.config] という名前のファイルを追加して、次の内容をコピーします。

image

再びサイトにアクセスすれば、次のような画面になります。

image

フォルダーやファイルを追加してみます。

image

すると、一覧として表示されます。

image

 

ファイルを配置する方法としては、
上記のように Visual Studio Online "Monaco" を使うほか、FTP を使うことができます

ディスクの容量については、無料プランでは 1GB までです。
その他のプランの場合は、価格 – App Service を参照してください。

参照
ディレクトリの参照 <directoryBrowse>
Azure Web App に FTP でデプロイする

カテゴリー: クラウド. タグ: . Leave a Comment »

Azure Web App の仮想ディレクトリにサブドメインを設定する

前回は Azure の DNS ゾーンでカスタム ドメインを使うという記事を書きましたが、
今回はさらに、Azure Web App の仮想ディレクトリにサブドメインを対応させる方法について書きます。

つまり、1 つの独自ドメインと 1 つの Azure Web App (Shared 以上) があれば、
複数のサブドメインをホストできるということです。

方針としては、DNS ゾーンではワイルドカード ドメインを設定して、
Azure Web App で仮想ディレクトリとサブドメインの対応を設定します。
例えば abc.com が abccom.azurewebsites.net に対応しているとしたら、
app1.abc.com を abccom.azurewebsites.net/app1 に対応するようにします。

以下、設定手順です。

 

DNS ゾーンの設定

DNS ゾーンでワイルドカード ドメインを受け付けるように設定します。
[レコード セットの追加] で次の 3 つのレコードを登録します。

@ A xxx.xxx.xxx.xxx (IP アドレス)
awverify CNAME awverify.app-name.azurewebsites.net
* CNAME app-name.azurewebsites.net

前回のときに www としていた部分を * (ワイルドカード) に変更しただけです。

レコード セット

 

Web App の設定

Azure Web App の [アプリケーション設定] – [仮想アプリケーションとディレクトリ] で仮想ディレクトリを作成します。

仮想アプリケーションとディレクトリ

指定された仮想ディレクトリには、Web Deploy や FTP などを使って Web アプリケーションを配置しておきます。
(詳細不明ですが、Web アプリケーション プロジェクトに Application Insights を追加しておかないと、
配置後に実行時エラーになりました。)

Web を発行

 

次に [カスタム ドメインおよび SSL] で、利用可能にしたいサブドメインを追加します。
これで、サブドメインへのアクセスもこの Web App で受け付けられるようになります。
(ここでワイルドカード ドメインを登録する方法もあるでしょう。)

カスタム ドメインおよび SSL

 

このままだと、サブドメインへのアクセスがすべてルートのアプリケーションに流れてしまいます。
そこで www 以外のサブドメインと仮想ディレクトリを対応させるため、URL Rewrite を使います。
ルートの Web アプリケーションの Web.config に次の設定を追加します。

 

以上で、test1.saka-pon.net または saka-pon.net/test1 の URL で仮想アプリケーションにアクセスできるようになりました。

サブドメイン

 

前回: Azure の DNS ゾーンでカスタム ドメインを使う

参照
Creating Rewrite Rules for the URL Rewrite Module
URL Rewrite Module 2.0 Configuration Reference
URL 書き換えモジュール構成のリファレンス
Windows IIS/Azure WebサイトのURL Rewrite機能でURLを書き換える(基本編)

Azure Web App に FTP でデプロイする
Visual Studio から Windows Azure にデプロイする

Azure の DNS ゾーンでカスタム ドメインを使う

Microsoft Azure には DNS ゾーンの機能がありますが、管理ポータルの GUI で設定ができるようになりました。
(以前は PowerShell で設定していたようです)
以下では、DNS ゾーンを設定して、Azure Web App をカスタム ドメインで使うための手順を示します。

前提として、次のものを用意します。

  • Web サイトに設定したい独自ドメイン
  • Web サイトの実体となる Azure Web App
    • この時点では app-name.azurewebsites.net の形式でのみアクセスできる
    • 独自ドメインを利用するには、価格レベルは Shared 以上が必要

この Azure Web App に、abc.com および www.abc.com の形式のドメインでアクセスできることを目標とします。

 

Azure 管理ポータルの [DNS ゾーンの作成] で、[名前] にはドメインを入力します。

DNS ゾーンの作成

これで DNS ゾーンが作成されます。
次に [レコード セットの追加] で、次の 3 つを登録します。

@ A xxx.xxx.xxx.xxx (IP アドレス)
awverify CNAME awverify.app-name.azurewebsites.net
www CNAME app-name.azurewebsites.net

Azure Web App の IP アドレスは、後述する [外部ドメインの使用] を開くと表示されます。
また、awverify は Azure Web App を利用する場合の固有のもので、作業者が同一であるかを確認するために必要です。
この設定がないと、後述する [外部ドメインの使用] でエラーとなります。

[名前] を空欄にすれば、自動的に @ (ルート) になります。

レコード セットの追加

レコード セットを追加すると、次の画面のようになります。
SOA レコードと NS レコードは最初から登録されています。

レコード セット

 

上の画面には「ネーム サーバー」がいくつか表示されています。
これらをドメイン管理サービスの DNS サーバーとして設定します。
次に示すのはデータ・ジャパンの管理サイトです。

DNS サーバー

基本的にはすぐにネットワークに設定が反映されますが、かなり時間がかかることもあるようです。
設定が反映されているかどうかは、Dig web interface などで確認できます。

Dig web interface

 

最後に、Azure 管理ポータルに戻り、Azure Web App の [カスタム ドメインおよび SSL] – [外部ドメインの使用] で
利用したいドメインを割り当てれば完了です。
ここでは、ドメインのルートのほか、www 付きのドメインも指定しています。

カスタム ドメインおよび SSL

ちなみに、DNS ゾーンで www のレコードを

www CNAME saka-pon.net

と設定した場合は、この [外部ドメインの使用] で www 付きのドメインを割り当てようとしたときにエラーとなりました。
(おそらく awverify が理由)

 

次回: Azure Web App の仮想ディレクトリにサブドメインを設定する

参照
Azure DNS の使用を開始する
Azure App Service のカスタム ドメイン名の構成
Windows Azure Web サイトに独自ドメイン ( カスタムドメイン ) を設定し使用する
Dig web interface

Azure Web App に FTP でデプロイする

Azure Web App にアプリケーションをデプロイする方法については、
これまでは主に、Visual Studio Team Services との CIGitHub との CI など、
ソース管理システムから自動的にデプロイする方法について書いてきましたが、
ソース管理システムと連携させない方法としては主に FTP を利用することになります。

FTP を利用するためには、Azure の管理ポータルで、
作成済みの Web App に対して [設定] – [デプロイ資格情報] と進んで、ユーザー名とパスワードを入力して [保存] をクリックします。

image

注意点として、ユーザー名はグローバルに一意でなければなりません (他の開発者と同じ名前を使用できません)。
また、サブスクリプション内のすべての Web App にもこのアカウントが設定されます。

これで、FTP を使うための準備ができました。
FTP の URI とユーザー名は Web App のトップに表示されています。

image

 

[FTPS ホスト名] の部分をコピーして、エクスプローラーでアクセスします。
ユーザー名もコピーできます。

image

これで、FTPS でアクセスできました。

image

あとは、wwwroot にアプリケーションをコピーすればデプロイは完了です。

image

 

また、Web App の [設定] – [アプリケーション設定] – [仮想アプリケーションとディレクトリ] で仮想アプリケーションを設定できます。
つまり、wwwroot 以外の物理ディレクトリも URL に関連付けることができます。

image

FTP でデプロイ:

image

ブラウザーでアクセス:

image

ちなみに、Monaco にアクセスすると既定の URL は /dev/wwwroot/ ですが、
ここを書き換えると wwwroot 以外も編集できるようになります。

image

 

ディスクの容量については、Free プランでは 1GB までです。
その他のプランの場合は、価格 – App Service を参照してください。

カテゴリー: クラウド. タグ: , . 2 Comments »

Azure Table の検索条件を LINQ で指定する

Azure Storage の SDK (Windows Azure Storage) を利用して .NET のクライアントから Table のデータを取得する際に、
検索条件を指定しようとすると、通常の実装では次のようなコードになり少し複雑です。
この例では、フィルター条件を 2 つ指定しています。


var query = new TableQuery<Person>()
    .Where(TableQuery.CombineFilters(
        TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "2015"),
        TableOperators.And,
        TableQuery.GenerateFilterConditionForInt("Age", QueryComparisons.LessThan, 20)));

var result = PeopleTable.ExecuteQuery(query).ToArray();


ここで、Person  は TableEntity を継承したクラスで、PeopleTable は CloudTable 型のオブジェクトです。

結局、上記の Where メソッドに渡されるのは、

(PartitionKey eq ‘2015’) and (Age lt 20)

という文字列になります。
これなら string.Format メソッドでもよいのではないのかという気もしますが、
プログラミングのミスを防ぐためには、フィルターや射影などの検索条件は LINQ で指定したいところです。

検索条件を LINQ で指定する方法として TableServiceContext クラスを使う方法もあるようですが、
現在は Obsolete 属性が指定されており、非推奨となっています。

とはいえ、自力で IQueryable<T> を実装するのも骨が折れるので、
ここでは簡易的に、TableQuery<T> の拡張メソッドとして Select および Where メソッドを実装していきます。
ラムダ式で指定された検索条件を式ツリーとして受け取って解析し、動的にクエリを生成します。

このような TableHelper クラスを実装することで、Azure Table の検索条件を LINQ で指定できるようになります。
ただし、文字列の不等式については、String クラスの演算子として不等号が定義されていないため、

p.LastName >= "W"

と書くことができず、

p.LastName.CompareTo("W") >= 0

のようにせざるを得ませんでした。

 

作成したサンプル
ExpressionsConsole (GitHub)

バージョン情報
Windows Azure Storage 6.0.0

参照
Windows Azure Storage
Expression<TDelegate> クラス
TableQuery<TElement> Class

Windows Azure Storage Extensions
テーブル サービスに対する LINQ クエリの作成 (古い形式)
TableServiceContext Class (古い形式)

Azure Event Hubs で送受信

あるアプリケーションから別のアプリケーションへデータを送信する方法として、
Microsoft Azure のイベント ハブ (Event Hubs) を利用できます。
イベント ハブは、小さいデータを短い間隔で送るというシナリオに向いています。
また、イベント ハブは文字通りハブとして機能し、送信側と受信側を多対多とすることができます。

今回は、基本的には公式のチュートリアルである Event Hubs の使用の方法をもとにして実装していきます。
(そのため、重複する内容は割愛することがあります。)

まず、Azure の管理ポータルでイベント ハブとストレージを作成します。
ストレージは、受信のための構成を保存しておく場所になるようです。

サービス バスの名前空間を sakapon-event-201508-ns、イベント ハブの名前を sakapon-event-201508 としました。

イベント ハブ

共有アクセス ポリシーには、SendRule と ReceiveRule を定義しておきます。

イベント ハブ

 

続いて、Visual Studio でプロジェクトを作成します。
今回は、送信側も受信側も WPF アプリケーションとして作成しました。

プロジェクトを作成したら、NuGet で、送信側には WindowsAzure.ServiceBus を、
受信側には Microsoft.Azure.ServiceBus.EventProcessorHost をインストールします。
このとき、App.config には接続文字列などの設定のためのテンプレートが追加されます。

以下、送信側および受信側の実装について説明します。

 

送信側の実装

まず、App.config の appSettings に、キーが Microsoft.ServiceBus.ConnectionString のエントリが生成されているので、
そこに SendRule に対応する接続文字列を指定します。

App.config

EventHubClient オブジェクトを初期化するときに、
サービス バスの名前空間ではなく、イベント ハブの名前を指定します。
特殊な指定方法ですが、これで接続文字列が .config ファイルから読み込まれます。

あとは、送りたいメッセージをバイナリ データ (byte[] や Stream) に変換して、
Send または SendAsync メソッドに渡すだけです。
複数の属性値を持つオブジェクトを送信するには、JSON などにシリアライズするとよいでしょう。

 

受信側の実装

送信側のときと同様、App.config に、ReceiveRule に対応する接続文字列を設定します。
なお、イベント ハブのほかに、ストレージの接続文字列も設定します。

EventProcessorHost オブジェクトを初期化するには接続文字列が必要になりますが、
送信側のときとは異なり、.config ファイルから透過的に読み込む機能はないため、明示的に接続文字列を取得しています。

App.config

通知されたイベントを実際に処理するクラスとして、IEventProcessor インターフェイスを実装したクラスを作成しなければなりません。
パーティション 1 つにつき、そのインスタンスが 1 つ生成されます。

ここでは StaticEventProcessor クラスを作成しましたが、
内部的に既定のコンストラクターが呼び出されて初期化されるため、外からデリゲートを渡すのが難しい構造です。
実装がややこしくなるため、この SDK には改良の余地があるように思えます。

 

さて、上記の実装をもとに、送信側の WPF アプリケーション (SenderWpf) をマウスなどでドラッグして移動させると
受信側の WPF アプリケーション (ReceiverWpf) が自動的に同じ座標に追従するというサンプルを作成しました。
完全なソースコードは EventHubsSample – GitHub にあります。

Event Hubs - sync apps

なお、その他の注意点は以下の通りです。

  • イベントの到着の順序は保証されません。
    (上のサンプルで非連続な動作があるのはそのためです。)
  • PartitionContext や EventData は一意の SequenceNumber を持ちますが、
    これらはパーティションの中で一意であって、コンシューマー グループ全体で一意になるわけではありません。
    したがって、メッセージに一意性を持たせるには、ID や時刻を含めて送信する必要があります。
  • それぞれのデータは、コンシューマー グループ 1 つにつき 1 回だけ配信されます。
    同じコンシューマー グループに設定したアプリケーションを 2 つ起動すると、
    受信するデータが半分ずつ程度に分散してしまいます。
    コンシューマー グループを追加することにより、送信側と受信側を多対多にすることができます。
  • PartitionContext.CheckpointAsync メソッドにより、イベントを受信したことを記録します。
    これが呼び出されないと、また同じイベントが通知されます。
    また、送信側が稼働しているのに受信側が稼働していない場合もデータは蓄積されているため、
    次に受信側を起動したときに大量に押し寄せてくることがあります。

 

作成したサンプル
EventHubsSample (GitHub)

バージョン情報
.NET Framework 4.5
WindowsAzure.ServiceBus 3.0.1
Microsoft.Azure.ServiceBus.EventProcessorHost 2.0.2

参照
Event Hubs の使用

カテゴリー: クラウド. タグ: , . Leave a Comment »