読者です 読者をやめる 読者になる 読者になる

割と普通なブログ

Microsoft Azure や ASP.NET、Java EE 系の話題を記載します

Windows Azure を使っていて気付いたポイントを書いてみる

C# Windows Azure

又してもWindows Azureを弄ったノウハウが溜まってきたので放出。突っ込み希望、質問等ももちろん希望!みんな、Windows Azureをもっといじろうじゃないか!!

*.cscfg と *.csdef ファイルの位置づけを理解せよ!!

Windows Azureの設定ファイルは *.cscfg と *.csdef の二つが存在します。こ奴らの位置づけとしては以下な物だと考えます。

  1. *.csdefファイル
    • ⇒ 設定値のキーだけ定義
    • ⇒ ポータルサイトにデプロイ後は変更不能
  2. *.cscfgファイル
    • ⇒設定値の値を定義
    • ⇒ ポータルサイトにデプロイ後は変更可能

以下、これ等設定ファイルの具体的な使用例を載せてみます。

  • csdefファイルの内容 〜定義だけだよw〜
  <WebRole name="CloudMvcApp" enableNativeCodeExecution="false">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings >
      <!-- 自分で定義した情報 -->
      <Setting name="MVC_Message" />
    </ConfigurationSettings>
  </WebRole>
  • cscfgファイルの内容 〜csdefファイルで定義したキーの値を定義〜
  <Role name="CloudMvcApp">
    <Instances count="1" />
    <ConfigurationSettings >
      <Setting name="MVC_Message" value="Hello Azure ASP.NET MVC なのだが、日本語OK?" />
    </ConfigurationSettings>
  </Role>

上記の設定ファイルに記述した内容について、ソースファイル内では以下の様に使用します。RoleManager#GetCongigurationSettingに、キー名の文字列を引数に与えると値が取得できます。

  • HomeController.cs (抜粋)
public ActionResult Index()
{
    ViewData["Message"] = RoleManager.GetConfigurationSetting("MVC_Message");
    return View();
}

が、本番環境にデプロイした際に大問題…。cscfgファイルで定義した値が日本語の場合、本番環境では以下の様に文字化けする模様、みんな気をつけよう!!

複数のWebロールを共存させる件について…

複数のWEBロールを一つのアーカイブにまとめてデプロイする場合、以下の様に接続ポートを変更します。

  • csdef ファイルの内容
  <WebRole name="LogWebRole" enableNativeCodeExecution="false">
    <InputEndpoints>
      <!-- ポート番号は8080 -->
      <InputEndpoint name="HttpIn" protocol="http" port="8080" />
    </InputEndpoints>
    (中略)
  </WebRole>
  <WebRole name="CloudMvcApp" enableNativeCodeExecution="false">
    <InputEndpoints>
      <!-- ポート番号は80 -->
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    (中略)
  </WebRole>

接続ポートが異なるので、もしもWEBロール間で遷移させたかったら、以下の様に書いたりすると行けます*1

public ActionResult Index()
{
    try
    {
        ViewData["Message"] = RoleManager.GetConfigurationSetting("MVC_Message");
    }
    catch (Exception e)
    {
        ViewData["Message"] = e.StackTrace;
    }

    ViewData["ASP_NET_URL"] = "http://" + Request.Url.Host + ":8080";

    return View();
}

Windows Azureのログシステムを使う…?

Azureでのログ出力ですが、コードとしては以下の形で出力されます。

    using Microsoft.ServiceHosting.ServiceRuntime;
    public class WorkerRole : RoleEntryPoint
    {
        public override void Start()
        {
            // ここでログの出力
            RoleManager.WriteToLog("Information", "Worker Process entry point called");

ローカル環境での実行では、Development Fabricからログ出力を確認可能です(以下の画像参照)。

本番環境ではDevelopment Fabricが存在しない為、どうやってログの確認をするのかなぁと思いまして、Windows Azure Platform Training Kitを探っていたところ、「WindowsAzurePlatformKit\Demos\WindowsAzureGuestBookLogging\Demo Script - Logging and Configuration.docx」に方法が載ってました。

が、中身を参照して手順どおりに作業を進めたところ、Azure ポータルサイトのlogginシステムが改善中になっている・・・。後日試す事にしよう・・・。
http://blogs.msdn.com/windowsazure/archive/2009/10/03/upcoming-changes-to-windows-azure-logging.aspx

北米に繋ぐのは重い&時間がかかる

試しに以下のASP.NETのコードを書いてみました。処理自体は

  1. 1秒ごとにポストバック処理をする
  2. 現在の日付・時刻を画面に描画する

だけを行う簡単な処理です。

  • Default.aspx(抜粋)
    <h1>
        ログ用のテストプロジェクト</h1>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:Label ID="NowTimeLabel" runat="server" Text="Label"></asp:Label>
    </div>
    <asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="Timer1_Tick">
    </asp:Timer>
  • Default.aspx.cs(抜粋)
protected void Timer1_Tick(object sender, EventArgs e)
{
    NowTimeLabel.Text = DateTime.Now.ToString();
    RoleManager.WriteToLog("Verbose", "Time1_Tick");
}
  • 動作イメージ


こ奴を実行したところ、ローカル環境では元気に動いていましたが、本番環境では更新される時間が2〜3秒ペースとなっております。うーん、この程度のポストバック処理で遅延するのは結構ダメージが大きそうだ…。

本番環境で日本語が入ったSite.Master使うと、文字化けをしてしまう

ASP.NET MVCを使っている人にとって、以下はおなじみの画面だと思います。まずは以下の画像をご覧ください。

赤で囲んでいる部分の日本語が文字化けしており、青い部分は日本語が文字化けしていません。実はこれ、Site.Masterの日本語 or Index.aspxの日本語かの違いしかないのです。ローカル環境では文字化けが起きないのですが、実行環境ではこの有様。うーむ…。

*1:もちろんhttp、8080の部分は環境変数から取得できますのであしからず