Windows Azure

Windows Azure Accelerator for Web Roles Version 1.1 | Nathan Tottenをざっくり意訳した投稿です。

今日、最初のWindows Azure Accelerator for Web Rolesのアップデート版をリリースしました。

このアップデートでは、バグフィックスといくつかの新しい機能追加が含まれています。このリリースは、旧バージョンのアクセラレーターと互換性があり、すでにデプロイしているアクセラレーターをアップデート版に置き換えることができ、サイトは同期し動作し続けます。この投稿では、幾つかの新しい機能と、幾つかの既知の問題の対処について紹介します。
もし、まだアクセラレーターを使用していない場合は、紹介エントリー(英語)を読むことをお勧めします。
日本語では、次のサイトで紹介されています。

MVC3とPHPに対応

アクセラレーターの最初の変更は、MVC3とPHPに使用できるようにしたことです。以前のバージョンでは、アクセラレーターを使用するにはスタートアップタスクによる対応が必要でした。多くの人からMVC3とPHPでの使用方法を聞かれたので、デフォルトで組み込むことにしました。MVC3とPHPで使用しない場合は、単純にConfigureIIS.cmd からスタートアップタスクを削除してください。

ログ記録の改善

2つ目の変更は、アクセラレーターのログ記録を改善したことです。トレースメッセージにメッセージを追加したり、メッセージを詳細に記載する改善をしました。この変更は、同期プロセスの理解と障害の解析の助けになります。

image_thumb4

 

同期プロセスのStartとStop

次に追加した機能は、同期プロセスの開始と停止ができるようにしました。通常、Webロールインスタンス上でサイトの更新と設定の変更などを確認するために、同期プロセスは動作をし続けます。このプロセスをあなたが止めたいと思うかもしれない2つの理由があります。

最初の理由は、既知の問題への対応のためです。大きなサイトをデプロイした時、デプロイが終了する前に、同期ツールが実際にサイトの取得を始めます。その為、インスタンス間で矛盾したデプロイになってしまいます。通常、大きなサイトのデプロイが完了した後、同期処理が再同期し整合性を回復します。
しかし、一時的に矛盾が発生する一部分の同期を避けたいと、あなたは考えるかもしれません。この理由に対応するには、大きなサイトをデプロイする時は、デプロイする前に同期を停止し、デプロイ完了後同期を開始することをお勧めします。

2つめの理由は、ストレージ転送量を抑えたい場合です。同期用の初期設定では、15秒ごとにブロブとテーブルストレージを確認します。さらに。同期が発生する度にログメッセージが書き込まれます。このため、1インスタンス1分につき12ストレージトランザクションが発生し、1か月におよそ518,400トランザクションになります。これは多いように思うかもしれませんが、10,000トランザクションにつき$0.01程度の費用であることを思い出してください。
同期にかかる費用は、一か月でたった$0.50です。会社によっては、多くのWindows Azureへのデプロイがあり、費用を抑えたい場合があります。デプロイするまで、同期プロセスを無効にすることで、一か月につき数ドルの費用を抑えることができます。

同期プロセスの開始と停止は、管理ページの上にあるリンク”Disable Sync”をクリックします。同期が無効になっているときは、管理ページの下部に次のようなメッセージが表示されます。

image_thumb5

テストサイトのバインド

次に追加した機能は、DNS変更やホストファイルへの変更を加えることなく簡単にサイトをテストすることができます。以前のリリースでは、mysite.example.comのようにホストヘッダーを使用しないとサイトを見ることができませんでした。今回のリリースでは、mysite.cloudapp.netからサイトをテストすることができるオプションを追加しました。
サイトを見るためにテストサイト機能を有効にするには、<myhost>.cloudapp.net/test/<sitename>とします。サイト設定を編集することで、オプションを有効にすることができます。

image_thumb6

Windows Azure CDNへの対応

テストサイトのバインドと同様に、CDNバインドを追加しました。Web Role AcceleratorサイトでWindows Azure CDN用を使用することができるようになりました。Windows Azure CDNは、<myhost>.cloudapp.net/cdn/からだけコンテンツをリクエストします。その為、バインドを作成するようにしました。<myhost>.cloudapp.net/cdn/<sitename>をバインドし、同じロールにある複数のサイトで動作するようにしました。
Windows Azure CDNへの対応を有効にするには、サイト設定ページで、”Enable CDN”にチェックを入れます。

image_thumb7

Windows Azure

How Microsoft IT Deployed a Customer-Facing Application to Windows Azure in Six Weeksを元ネタに投稿したエントリーです。

Microsoftボリュームライセンスサイトで提供しているOnline Product Use RightsとOnline Service Provider Use RightsツールをWindows Azure上に移行しました。

既存の構成

Figure 1. Online PUR legacy architecture

マイグレーション後の構成

Figure 2. Final Windows Azure architecture for the Online PUR/SPUR tool

Windows Azure

Not enough space on the disk – Windows Azure | Matias Woloski」をざっくり意訳した投稿です。

ローカルストレージ容量が容量が少なくて、Windows Azureで容量不足が発生します。ServiceDefで容量増加をすることで簡単に解決することができます。WebDeployを使用すると度々この問題に直面します。解決方法について情報共有したいと思います。

問題

パッケージを作成する時、WebDeployがディスク容量不足の例外が発生します。

There is not enough space on the disk. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count) at System.IO.BinaryWriter.Write(Byte[] buffer, Int32 index, Int32 count) at Microsoft.Web.Deployment.ZipEntry.ReadFromFile(String path, Boolean shouldCompress, BinaryWriter tempWriter, Stream stream, FileAttributes attr, DateTime lastModifiedTime, String descriptor, Int64 size) at Microsoft.Web.Deployment.ZipEntry..ctor(String path, DeploymentObject source, ZipFile zipFile)

Windows Azure

image

ASP.NET Univarsal Providers のセッションプロバイダを使ってみる」で、次のような紹介がありました。

ASP.NET Univarsal Providersのセッションプロバイダって、セッションの破棄もしてくれるの?という話題から。結論から言うと、「期限切れのセッションは削除してくれます。但しパフォーマンスに問題がありそうなやり方で。」となります。

定期ジョブを処理する機能SQL Server Agentが提供されていないSQL Aureへの対応としては仕方ないと思います。とは言え、アクセスの度に何をしているのかを調べてみようと思います。

毎回アクセス時にしていること(SQL的にね)

アクセスした時間に、セッション有効時間切れしてるものがあるかどうかを確認します。

SELECT
[Extent1].[SessionId] AS [SessionId],
[Extent1].[Created] AS [Created],
[Extent1].[Expires] AS [Expires],
[Extent1].[LockDate] AS [LockDate],
[Extent1].[LockCookie] AS [LockCookie],
[Extent1].[Locked] AS [Locked],
[Extent1].[SessionItem] AS [SessionItem],
[Extent1].[Flags] AS [Flags],
[Extent1].[Timeout] AS [Timeout]
FROM [dbo].[Sessions] AS [Extent1]
WHERE [Extent1].[Expires] < @now’

@now datetime2(7) 2011-08-07 06:38:04.1649431

期限切れのセッションがあれば、セッション情報を削除します。

delete [dbo].[Sessions]
where ([SessionId] = @0)

自分のセッション情報を取得します。

SELECT
[Limit1].[SessionId] AS [SessionId],
[Limit1].[Created] AS [Created],
[Limit1].[Expires] AS [Expires],
[Limit1].[LockDate] AS [LockDate],
[Limit1].[LockCookie] AS [LockCookie],
[Limit1].[Locked] AS [Locked],
[Limit1].[SessionItem] AS [SessionItem],
[Limit1].[Flags] AS [Flags],
[Limit1].[Timeout] AS [Timeout]
FROM ( SELECT TOP (1)
    [Extent1].[SessionId] AS [SessionId],
    [Extent1].[Created] AS [Created],
    [Extent1].[Expires] AS [Expires],
    [Extent1].[LockDate] AS [LockDate],
    [Extent1].[LockCookie] AS [LockCookie],
    [Extent1].[Locked] AS [Locked],
    [Extent1].[SessionItem] AS [SessionItem],
    [Extent1].[Flags] AS [Flags],
    [Extent1].[Timeout] AS [Timeout]
    FROM [dbo].[Sessions] AS [Extent1]
    WHERE [Extent1].[SessionId] = @id
)  AS [Limit1]

@id nvarchar(4000) lbw5dkyodyilchsipwuzo5dj/LM/W3SVC/1273337584/ROOT

無かったら、セッション情報を格納します。

insert [dbo].[Sessions]([SessionId], [Created], [Expires], [LockDate], [LockCookie], [Locked], [SessionItem], [Flags], [Timeout])
values (@0, @1, @2, @3, @4, @5, @6, @7, @8)

もっかい自分のセッション情報があるかを確認しセッション情報があれば、セッション情報の有効期限を更新します。

update [dbo].[Sessions]
set [Expires] = @0, [LockDate] = @1, [Locked] = @2
where ([SessionId] = @3)

まとめ

一回のアクセスで、都合8SQL流れているように見えます。アクセスする度に8SQL流れ、アクセスの都度セッションの有効期限を更新しています。

SessionテーブルのExpiresにインデックスを貼ってないので、アクセスの度にフルスキャンが走るのは間違いありません。しかし、データ量が少ない場合はインデックスが貼ってあっても、インデックスを使用せずにテーブルをフルスキャンします。一方、アクセスする度に有効期限の日付を更新するUpdate文が流れますので、インデックスが貼ってあると更新時のコストが増加します。

どのタイミングでインデックスが貼ってある効果が出るかまでは今回調べてませんが、同時セッション数10~20程度であれば、インデックスが無い方がパフォーマンス上優位だと思います。
同時セッション数が多いシステムで運用する場合には、インデックスを作成するとパフォーマンス改善する可能性があります。

Windows Azure

image

Windows Azure ASP.NET MVC 3 Web Role で使っているプロバイダ « ブチザッキで、

どうもこのASP.NET MVC 3 Webロールテンプレートで使っているセッションやメンバシッププロバイダ等各種プロバイダはEntityFrameworkベースのSystem.Web.Providersだそうです。

なんて紹介されています。
System.Web.Providersって、何やつ?どー使ってあげれば良いの?
ってことで、答えを「Deploying the Windows Azure ASP.NET MVC 3 Web Role」から拝借してきました。

MVC 3テンプレートでは、ASP.NET Universal Providerを使用しています。
セッションステートの格納先が初期設定では、SQL Expressを使用するようにしているASP.NET Universal Providerをテンプレートでは、使用しています。

<sessionState mode="Custom" customProvider="DefaultSessionProvider">
  <providers>
    <add name="DefaultSessionProvider"
         type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
         connectionStringName="DefaultConnection"
         applicationName="/" />
  </providers>
</sessionState>

さて、ベストな対応はなんでしょうか?

SQL Azureにシンプルなデータベース「UniversalProviders」を作成します。

image

接続文字列をコピーし、所りゅーしょんのApplicationServiesDefaultConnection接続文字列をSQL Azureの接続文字列に変更します。

接続文字列では、MultipleActiveResultSets=True と設定する必要があります。

<connectionStrings>
  <add name="ApplicationServices"
       connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;"
       providerName="System.Data.SqlClient" />
  <add name="DefaultConnection"
       connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;"
       providerName="System.Data.SqlClient" />
</connectionStrings>

後は、Windows Azureにデプロイすれば動作します。

動作させた後、データベースを確認すると「dbo.Sessions」テーブルが作成されています。

ログオンし、ユーザのセットアップをすると、Windows Azureで動作するMVCアプリケーション内のメンバーシップとロールがすべてSQL Azureに格納されます。

Picture