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

SQL Azure

Handling Error 40552 IN SQL Azureをざっくりと日本語訳した投稿です。

エラー40552が発生する理由

SQL Azureは、サーバを複数ユーザで共有するクラウドデータベースサービスです。
全ユーザが等しくSQL Azureを快適に使えるように、一部のユーザがリソースを占有しないように幾つかのセーフ機能を持っています。

セーフ機能の1つに、トランザクションで大量にアクティブトランザクションログを生成していないか監視しています。
大量のトランザクションログ容量を使用するトランザクションを実行しているアプリケーションは、SQL Azureから次のエラーを受け取ることになります。

Msg 40552, Level 20, State 1, Line 1
The session has been terminated because of excessive transaction log space usage. Try modifying fewer rows in a single transaction.

インデックスの作成、再構築、削除をする際に40552を回避する方法

インデックスの削除、再構築、作成は、大量のトランザクションログレコードを生成するので、大きなテーブル上でこのエラーメッセージを受け取る可能性があります。

この問題を回避する為に、新しいテーブルを作成しインデックスのレイアウトを完成され、その新しいテーブルに小さな粒度でデータを移行します。
しかし、たいていの場合、ONLINEオプションを使用してインデックス操作をするほうが、必要なトランザクションログスペースを少なくすることができます。
ONLINE=ONを指定して、CREATEやALTER、DROP INDEX操作をすると、実行方法が変わります。
一つの大きなトランザクションに変わって、長時間広いロックを取得することなく、裏側で複数の小さなトランザクションを実行する操作になります。

どちらの方法でも、操作に必要なトランザクションログ容量を減らすことができ、操作を実行している間でも、対象テーブルの使用を継続できます。

Windows Azure

MSDN Blogsをざっくりと日本語訳した投稿です。

Microsoft Visual Studio 2010用Windows Azure Toolsの2011年8月リリースについて発表できて、とっても嬉しいです。Web Platformインストーラーを使用して、ここからツールをダウンロードできます。

本リリースの新しい点

  • Windwos Azureで動作するアプリケーションのプロファイル
  • ASP.NET MVC3 Web Roleの作成
  • 一つのクラウドプロジェクトで複数のサービス設定の管理
  • Windows Azure パッケージの問題チェック機能の改善

Windwos Azureで動作するアプリケーションのプロファイル

Windows Azure Toolsが、プロファイリングをサポートしたことで、Windows Azureで動作するアプリケーションのパフォーマンスボトルネックを簡単に見つけることができるようになりました。

 

ASP.NET MVC3 Web Roleの作成

新しいToolsでMVC3 Web Roleの作成に対応しました。この新しいテンプレートは、SQL Azureに対応したユニバーサルASP.NETプロバイダーを含んでおり、Windows Azureに配置したときに、作成したアプリケーションとMVCアセンブリを配置します。

 

一つのクラウドプロジェクトで複数のサービス設定の管理

複数の配置環境ごとに、異なる設定を指定したい場合、Windows Azure Toolsは同じWindows Azure Projectで複数のサービス設定に対応しました。ローカルデバッグ、クラウド上での動作など、異なるWindows Azure Storageの接続文字列などを管理することができます。

 

Windows Azure パッケージの問題チェック機能の改善

最後に、新しいツールでは、Windows Azureにアプリケーションを配置する時に発生する、幾つかの共通的な問題を回避する手助けをします。パッケージにローカルアセンブリを含め忘れたり、ローカルAzure Storage接続文字列で配置しようとしたら、Toolsはあなたに知らせてくれます。

 

関連情報

さらに詳細を知りたい場合は、What’s New in the Windows Azure Toolsを参照してください。

このリリースに関連して、Windows Azure Platform トレーニングキットを新しいツール用にアップデートしました。Download Details – Microsoft Download Center – Windows Azure Platform Training Kitからダウンロードすることができます。