Windows Azure Storage Release - CORS、JSON、Minute Metrics の紹介

Windows Azure Storage Team Blogで、新しいWindows Azure Storageのリリースが紹介されています。Windows Azure Storage Release - Introducing CORS, JSON, Minute Metrics, and More

以下に抜粋で内容を紹介します。

3つの主要な機能

  1. CORS (Cross Origin Resource Sharing):Windows Azure Blobs, Tables, Queues でCORS が有効できるようにになった。これによって、browser から異なったドメインのリソースへのアクセス・操作ができる。CORS は、Service Properties の 設定で有効化。詳しくはhttp://msdn.microsoft.com/en-us/library/windowsazure/dn535601.aspxを参照してください。

  2. JSON (JavaScript Object Notation): 現在、Windows Azure Table は、OData 3.0JSON formatをサポートしている。JSON format では、AtomPub XML payloadの冗長な部分が削減されより効率的な転送になる。

    JSONは下記3つの形式でサポート

    • No Metadata - これは最も効率的なformatで、クライアントがカスタムプロパティのデータ型を知っている場合に便利です
    • Minimal Metadata - この形式は、暗黙的に解釈できない特定の種類のカスタムプロパティのデータ型情報が含まれている。例えば、Azure Table Browserのような、一般的なツールのように保存されているEntityのデータ型を知らないで読まなければいけない場合に便利です
    • Full Metadata - このフォーマットは、 generic OData readers で読む場合に便利です

    Windows Azure TableのJSONについての詳細情報はhttp://msdn.microsoft.com/en-us/library/windowsazure/dn535600.aspxを参照してださい。

  3. Windows Azure Storage Analytics の Minute Metrics: 今まで、Windows Azure StorageのMetricsは時間集計でした。(Storage Analytics Metrics の詳細) 新しい 2013-08-15 version では、 いくつかの主要な値に付いて 5分以内に 分集計(Minute Metrics) が取得できるようになります。それに伴って下記のテーブルを追加します。

    • $MetricsHourPrimaryTransactionsBlob
    • $MetricsHourPrimaryTransactionsTable
    • $MetricsHourPrimaryTransactionsQueue
    • $MetricsMinutePrimaryTransactionsBlob
    • $MetricsMinutePrimaryTransactionsTable
    • $MetricsMinutePrimaryTransactionsQueue

    時間集計のテーブル名が変わっているので注意してください。古いテーブルも継続して存在します。

    分集計の設定は、2013-08-15 version を設定して、Set Service Properties REST APIを使います。現在 Windows Azure Portal では設定ができませんが、将来サポートされる予定です。

    詳細情報は、About Storage Analytics Metricsを見てくだい。

その他の追加機能

これらの他の2013-8-15 versionでは、以下の機能を実装しています。2013-8-15 version の変更詳細のリストは:http://msdn.microsoft.com/en-us/library/windowsazure/dd894041.aspxにあります。

  • Copy blob で、Shared Access Signature (SAS) を、コピー先にも適応します。(同じstorage accountの場合)
  • Windows Azure Blob service は、Content-Disposition と response headers の cache-control などの ability control (via. SAS)をサポートします。Content-Disposition は、Set Blob Properties で設定します。
  • Windows Azure Blob service は、Get Blob と Get Blob Propertiesで、複数の HTTP conditional header をサポートします。この機能は、web-browsers which から CDN servers 経由でアクセスする場合に有用です。
  • Windows Azure Blob Service は、uncommitted blobはある状態での、Delete Blob operation をサポートします。以前は、事前にcommitしないとdelete Blob出来ませんでした。
  • List Containers, List Blobs と List Queues は、2013-08-15 version から、resourceに、URL address field を含みません。 これは、clientで再構築できる fields を削減したためです。
  • Lease Blob と Lease Container は、2013-08-15 version から、ETag と Last Modified Time を response headers で返します。これによって、lease holder は最後に見た時から、リソースが変更されたかどうかを簡単に確認することができます。(つまり、blob や その metadata が更新されたか)。以前と同じくblob の lease operations では、ETagは変更されません。

これらの機能に対応した、Windows Azure Storage Client Library をgithub:azure-storage-netにリリースします。数ヶ月で、Windows AzureのSDK 2.2、Windows Azure Storage Emulatorのアップデートをリリースする予定です。この更新は、2013-08-15 version の新機能をサポートします。

既知の問題が幾つかあります。下記の記事を参照してください。

http://blogs.msdn.com/b/windowsazurestorage/archive/2013/11/23/windows-azure-storage-known-issues-november-2013.aspxhttp://blogs.msdn.com/b/windowsazurestorage/archive/2013/11/23/windows-azure-storage-breaking-changes-for-windows-azure-tables-november-2013.aspx

以上

最後に

Azure Storage Client (Windows Azure Storage)は、3.0.0がリリースされています。nugetはnuget:WindowsAzure.StorageDependenciesを見ると、Microsoft.Data.OData 5.6以上になっているので、既存のコードとコンフリクトするかもしれません、要注意です。BUILD 2013で話が出てきたStorageの新機能の一部がまだ出てきていないようなので、年末に向けてさらに期待しています。負荷試験している時とかはMinute Metricsは便利ですね、嬉しいです。

Helios を Azure Cloud Service で使う

2013/12/13 追記 Microsoft.Owin.Host.IIS 0.1.1-pre では、WebRoleのStartup taskの作成 の問題は解決されました。

巷で話題のHeliosをCloud Serviceで使おうとしたらちょっとハマりました。基本的には、Checking out the Helios IIS Owin Web Server Hostと同じですが、Cloud Service、WebRoleの組み合わせでDeployしたら下記のようなエラーになります。

../../../_images/2013_11_helios009.png

最初、なにかアセンブリが足りないのかと思って、Fusion Logを調べたりしていたのですが、結局Helios内で使っているnavite code dllが依存しているVC12のランタイムが無かったという話でした。startup taskを用意してVC12のランタイムを入れてやると上手く動くようになります。

ここでは、Cloud Serviceの作成から、Heliosの組み込み、startup taskの作成まで一通り説明します。

手順の確認


WebRoleの作成からHeliosのインストールまで

  1. Cloud Service を作ってWebRoleを追加します普通にCloudServiceを作成し、WebRoleを追加します。テンプレートはEmptyにします
../../../_images/2013_11_helios003.png
  1. projectを、.NET 4.5.1 を使うようにします
../../../_images/2013_11_helios004.png
  1. コンパイルして問題無いのを確認します。

  2. System.Webの参照を全て削除します

  3. nugetを使って、Microsoft.Owin.Host.IISをインストールします:

    Install-Package Microsoft.Owin.Host.IIS -Pre
    

下記のような参照になります

../../../_images/2013_11_helios006.png

Startup Classの設定

下記のようなStartup classのコードを追加します:

using System;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebRole1.Startup))]

namespace WebRole1
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {

            app.Run(async context =>  // IOWinContext
            {
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/html";

                await context.Response.WriteAsync("Hello Herios. Time is: " + DateTime.Now.ToString());
            });
        }
    }
}

これで、WebRoleを動かしてみて、動くことを確認します。

WebRoleのStartup taskの作成

Helios 0.1.0の中で使われている、unmanaged codeがmsvcr120.dllに依存しているので、動作環境ではVC12 のランタイムが必要です。ここでは、WebRoleのstartup taskでVC12のランタイムをインストールする方法を説明します。

../../../_images/2013_11_helios007.png

ServiceDefinition.csdefに下記の定義を追加します:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="HelloHelios" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-10.2.2">
  <WebRole name="WebRole1" vmsize="Small">
    <Startup>
      <Task commandLine="startup.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

    <Sites>
    以下省略・・・・

WebRoleのプロジェクトに、startup.cmdというbatchファイルとvcredist_x64.exeを追加して、プロパティで出力ディレクトリにコピーするように設定します。

startup.cmd::
vcredist_x64.exe /install /quiet

vcredist_x64.exe は、Visual Studio 2013 の Visual C++ 再頒布可能パッケージからダウンロードできます。VS 2013をインストールしている場合は、C:Program Files (x86)Microsoft Visual Studio 12.0VCredist等のディレクトリにファイルがあります。

startup taskについて:Windows Azure でスタートアップ タスクを実行する

osFamilyの変更

.NET Framework 4.5.1は、Windows Server 2012R2では最初から入っています。簡単なので、osFamilyを4にして.NET Framework 4.5.1を使います。

ServiceConfiguration.(Local|Cloud).cscfgのosFamilyを3から4に変更します:

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="HelloHelios" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2013-10.2.2">
  <Role name="WebRole1">

まとめ

Helios 0.1.0runtimeには、native codeのDLLが含まれている。このDLLは、VC12(VS2013)のランタイム、msvcr120.dllに依存している。msvcr120.dllは、Cloud Service のWindows 2013R2 サーバーに存在しない。vcredist_x64.exeを使うとmsvcr120.dllがインストールされて問題が解決する。この問題は、厳密に言うとMicrosoft.Owin.Host.IIS 0.1.0-preが使っている、Microsoft.AspNet.Loader.IIS 0.1.0-preに起因する。このままだとちょっと使いづらいですね。

2013/12/13 追記

2013/12/02Microsoft.Owin.Host.IIS 0.1.1-preでは、Microsoft.AspNet.Loader.IIS 0.1.1-preに含まれる。Microsoft.AspNet.Loader.IIS.Interop.dll がMSVCR120.DLLに依存しなくなりました。そのため、WebRoleのStartup taskの作成のようなことをしないでも動作します。これで普通に使えるようになりますね。

../../../_images/2013_11_helios011.png

Windows Azure Storage Known Issues 2013/11

2013/11/29 以下の内容は正式な日本語訳が出ています Windows Azure ストレージの既知の問題
2013/11/30 Table Query での Cast 問題 が解決されたStorage Client Libraryがリリースされています。検証記事 Storage Client 2.1.0.4 以降での Cast問題の修正

cros, json 対応などのmajor releaseの準備に伴って実装が変更されているようです。それが原因でいくつかの意図しない問題が発生していることが報告されています。以下は Windows Azure Storage の BlogWindows Azure Storage Known Issues (November 2013)からの抜粋です。これらの問題が修正されプロダクションに公開され次第 Blog の記事は更新されるということです。

Windows Azure Blobs, Tables and Queue Shared Access Signature (SAS)のIssue

  • 下記のような、2012-02-12 バージョンのSASが、 HTTP Status Code 400 (Bad Request)になります。従来の実装だと、コンテナの前の“//”は、“/”に折りたたまれて処理されていましたが、現時点ではコンテナが無効である(null)として解釈されてしまいます。これは、修正される予定ですが、当面は“//”を送らないようにして下さい

http://myaccount.blob.core.windows.net//container/blob?sv=2012-02-12&si=sasid&sx=xxxx

Windows Azure TablesのIssue

下記の2つの既知のissueがあります。サービス側または当社のクライアント·ライブラリの一部としてhotfixを出す予定です。

  1. clients で、DataServiceContext.ResolveNameを定義し、<Account Name>.<Table Name>以外の型の名前を指定すると、CUD operation が 400 (Bad Request) を返します。これは、新しい実装では、ATOM の “Category” element の term 属性が、<Account Name>.<Table Name> と同じで無ければいけないのが原因です。以前のバージョン(実装)では、送信された型の名前は無視していました。これは再び無視するように修正される予定ですが、それまでの間は次の回避策を検討してください。ResolveName の設定は、Azure Tables では必要無いのでclient application のから外してください。そうすると OData の “category” element は送信されません。

下記は問題が発生するコードの例です。これを実行するとサーバー側で失敗します。

CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
TableServiceContext tableServiceContext = cloudTableClient.GetDataServiceContext();
tableServiceContext.ResolveName = delegate(Type entityType)
{
// This would cause class name to be sent as the value for term in the category element and service would return Bad Request.
return entityType.FullName;
};

SimpleEntity entity = new SimpleEntity("somePK", "someRK");
tableServiceContext.AddObject("sometable", entity);
tableServiceContext.SaveChanges();

この Issue の解決のためには client 側でtableServiceContext.ResolveNamedelegate の設定を外してください。

  1. service updateの一環として、サーバー側で使っている新しい .NET WCF Data Services library は、$filter query の 一部に empty “cast” があると 400 (Bad Request) で拒否します。古い .NET framework libraryではそうではありませんでした。これによって、Windows Azure Storage Client Library 2.1のIQueryable implementationに影響が出ます。.NET の DataServiceContext の挙動を、cast を送信しないようにクライアントライブラリを修正中です。これは、数週間以内に利用できるようになります( this should be available in the next couple of weeks )それまでの間次の回避策を検討してください。このクライアントライブラリの問題では、IEnumerable<T> で ITableEntityインターフェイスに制約するのでは無く、インスタンス化される型を明示的に使うことで回避できます。

下記は問題があるコードです

static IEnumerable<T> GetEntities<T>(CloudTable table)  where T : ITableEntity, new()
{
    IQueryable<T> query = table.CreateQuery<T>().Where(x => x.PartitionKey == "mypk");
    return query.ToList();
}

このように書くと 2.1 storage client library の IQueryable interface は、下記のUriに展開されて新しい service updateでは、400 (Bad Request) で拒否されます

http://myaccount.table.core.windows.net/invalidfiltertable?$filter=cast%28%27%27%29%2FPartitionKey%20eq%20%27mypk%27&timeout=90

コードを下記のように変更してquery の castを取り除いてください。そうすれば、cast operator は送信されません

IQueryable<SimpleEntity> query = table.CreateQuery<SimpleEntity>().Where(x => x.PartitionKey == "mypk");
return query.ToList();

Uri request は下記のようになり、service に受け付けられます

http://myaccount.table.core.windows.net/validfiltertable?$filter=PartitionKey%20eq%20%27mypk%27&timeout=90

We apologize for these issues and we are working on a hotfix to address them. (我々はこれらの問題について謝罪し、我々はそれらに対処するための修正プログラムに取り組んでいます)

感想、コメント等

  • 最後の Uriに cast operatorが出てしまって、それがあるとサーバーではねられて 400 (Bad Request) というのは嵌りそうです。回避策もなかなか厳しい気がします。
  • コンテナの前が//になってるとSASが効かないっていうのは、自前でUriを作成していると起きそうな気がします。要注意ですね。
  • ResolveName の件は、DataServiceContextにあって、TableServiceContextでは動作に関係しないものという混乱の原因になりがちなやつです。元々意味無かったはずなので、外せば良いと思います。

Windows Azure Tables の Breaking Changes 2013/11

2013/11/29 以下の内容は正式な日本語訳が出ています Windows Azure テーブルにおける重大な(互換性のない)変更

Azure Storage Team より、Windows Azure Table のJSONサポート準備のため Table の response が一部変更されている旨アナウンスされました。基本的に、HTTP、AtomPubの規格内の変更で互換性を保てるように最大限の努力をしているということですが、自前のカスタムパーサーを書いている場合などは問題になるかもしれません。

Windows Azure Tables Breaking Changes (November 2013)から変更点を紹介します。

変更点

  1. 新しいリリースでは、AtomPub response は、XML要素の間に改行、空白がありません。
  2. AtomPub XML Responce内のXML element(title、idなど)は、順番が変更される場合があります。
  3. HTTP HeaderのContent-Typeに”type” placeholder が追加されました。例えば, query の response (point query以外) は、content type に charset と application/atom+xmlに、type=feedが追加されます変更前: Content-Type: application/atom+xml;charset=utf-8変更後: Content-Type: application/atom+xml;type=feed;charset=utf-8
  4. MIME type のセキュリティ リスクの削減のための新しいresponse headerX-Content-Type-Options: nosniffが返されます。参照:http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx

感想等

  • 手元のアカウントで確認してみたら既に上記の通りに変更されていました。事前に予告が欲しいです。
  • 改行、空白が無くなった件は、今までのは、「XMLが element毎に改行されインデントされてるようなフォーマットで人が読むわけではないのに転送データ量が増えてMOTTAINAI」と思ってたので妥当な変更な気がします。これは、普通のXML parsersを通していれば問題になることは無さそうですし。
  • XML element の順番の件は引っかかるとちょっと面倒ですが、元々AtomPubの仕様に沿ったものなので無茶な話ではないと思います。
  • AtomPub内のXML elementの順番に関しては、RFC 4287 The Atom Syndication Format 日本語訳が参考になります。feedの中のelementはどんな順番で出てきても良いことになっていますね。
  • HTTP ヘッダーの変更は、ここまでパースしていることがあまり無いような気がするので、「影響はあまり無いのかな」という気がします。

json対応に向けて着々と進んでいるのは、とても嬉しいです。