.NET および Windows Phone 8 向けストレージ クライアント ライブラリ 2.1 RC の概要
このポストは、7 月 12 日に投稿された Windows Azure Storage Team Blog の Introducing Storage Client Library 2.1 RC for .NET and Windows Phone 8 の翻訳です。
マイクロソフトは、.NET および Windows Phone 8 向けストレージ クライアント ライブラリのリリース候補版 (RC) 2.1 の一般公開を発表しました。このブログ記事では、今回のリリース 2.1 でサポートされた拡張機能の詳細をご説明します。
RC 版を公開した経緯
マイクロソフトでは、ストレージ クライアントのリリース間隔を短縮し、クライアントのフィードバックに対してより迅速に対応できるように、多大な労力を注いでいます。この取り組みの一環として、次期リリースの RC 版を皆様に提供してフィードバックをお寄せいただき、「公式」リリースの改善に役立てたいと考えています。このリリース候補版は、皆様からフィードバックをいただくことを目的として公開いたします。ぜひご意見をお寄せください。
新機能
このリリースには多数の新機能が盛り込まれています。これからご紹介する新機能の多くは、クライアントのフィードバックを直接採用したものです。皆様からのご意見はこのような形で活用させていただいておりますので、今後ともぜひお気軽にお寄せください。
非同期タスク メソッド
特定の操作を目的としたタスクを返す非同期メソッドが、各パブリック API について新たに公開されました。さらに、これらのメソッドでは、CancellationToken が適用されるオーバーロードを使用して、プリエンプティブに取り消しを実行することができます。.NET 4.5 で実行している場合、または Async Targeting Pack for .NET 4.0 (英語) を使用している場合は、ストレージに関連するアプリケーションを作成する際に、Async または Await を使用したパターンを簡単に利用できます。
テーブルの IQueryable
リリース 2.1 では、デスクトップおよびモバイル デバイス向けのテーブル サービス レイヤーで、新たに IQueryable がサポートされます。これにより、WCF Data Services と同様に、LINQ 経由でクエリの構築および実行が可能になります。ただし、これは Windows Azure テーブル、および NoSQL の概念に向けて特別に最適化されたものです。次のスニペットは、新しく実装された IQueryable を使用したクエリの構築例です。
var query = from ent in currentTable.CreateQuery<CustomerEntity>()
where ent.PartitionKey == “users” && ent.RowKey = “joe”
select ent;
IQueryable の実装により、継承が透過的に処理されます。また、RequestOptions、OperationContext、およびクライアント側の EntityResolvers を式ツリーに直接追加できるようになります。これを使用する場合は、Microsoft.WindowsAzure.Storage.Table.Queryable 名前空間に using 文を追加した後、CloudTable.CreateQuery<T>() メソッドでクエリを構築します。さらに、これは既存のインフラストラクチャを利用しているため、IBufferManager やコンパイル済みシリアライザーなどの最適化機能、およびログ記録が完全にサポートされています。
バッファーのプール
大規模なアプリケーションにおいて、バッファーのプールは、クライアントがさまざまな処理の実行に既存のバッファーを再利用するうえでとても重要な手法です。.NET などの管理環境下では、割り当て処理、およびその後に準長期的に保存されるバッファーのガベージ コレクションの際に消費されるサイクル数を、大幅に減少させることができます。
このような状況に対処するため、各サービス クライアントでは、IBufferManager 型の BufferManager プロパティを公開しています。このプロパティにより、クライアントは、割り当てられたバッファー プールを、任意の関連付けられたオブジェクトと共にサービス クライアントのインスタンスに対して使用できます。たとえば、CloudTableClient.GetTableReference() により作成されたすべての CloudTable オブジェクトは、関連付けられたサービス クライアントの BufferManager を使用します。IBufferManager は、System.ServiceModel.dll の BufferManager の後にパターン化されます。これにより、デスクトップ クライアントは、フレームワークにより提供された既存の実装を容易に使用できるようになります (WinRT または Windows Phone などの他のプラットフォーム上で実行されているクライアントでは、IBufferManager インターフェイスに対してプールが実装されることがあります)。
マルチバッファー メモリ ストリーム
マイクロソフトは、パフォーマンス調査の実施中に、BCL で提供される MemoryStream クラスで、パフォーマンスに関する問題を複数発見しました。これらは特に、非同期処理、可変長の場合の動作、1 バイト処理に関するものでした。これらの問題を解決するために、データ長が不明な場合でも一定のパフォーマンスを発揮する、新しいマルチバッファー メモリ ストリームを実装しました。このクラスでは、バッファーの割り当てが追加されたときに、クライアントから IBufferManager の提供があった場合、これを利用してバッファー プールを使用します。その結果、任意のサービスにおいて、データのバッファリングを使用する任意の処理 (Blob ストリームやテーブル操作など) で CPU 負荷が減少し、共有メモリ プールが適切に使用されるようになります。
.NET MD5 が既定に
マイクロソフトがパフォーマンス テストを実施したところ、FISMA に準拠したネイティブな MD5 の実装は、.NET で構築された実装よりも多少のパフォーマンス低下が見られることが判明しました。このため、今回のリリースでは既定で .NET MD5 を使用するように設定されています。FISMA への準拠が必要な各クライアントでは、下記の方法で再有効化できます。
CloudStorageAccount.UseV1MD5 = false;
クライアントのトレース
リリース 2.1 では .NET トレース機能が実装されました。これにより、要求実行および REST 要求に関するログ情報を記録できるようになりました。ログが記録される情報の種類は、下の表でご確認ください。さらに、Windows Azure 診断ではトレース リスナーが使用できます。これは、クライアントのトレース メッセージをクラウドに保持する場合に、WADLogsTable にリダイレクトするものです。
.NET でのトレースを有効にする場合、トレース対象のストレージ クライアントを app.config に追加し、詳細を設定する必要があります。
<system.diagnostics>
<sources>
<source name="Microsoft.WindowsAzure.Storage">
<listeners>
<add name="myListener"/>
</listeners>
</source>
</sources>
<switches>
<add name="Microsoft.WindowsAzure.Storage" value="Verbose" />
</switches>
…
これで、ストレージ クライアントで生成されたすべてのトレース メッセージを、Verbose のレベルまでアプリケーションでログ記録するように設定されました。特定のクライアントまたは要求に対するログのみをクライアントで記録する場合は、OperationContext.DefaultLogLevel の設定を更新してアプリケーションの既定のログ レベルを変更した後、ログを記録する要求を OperationContext オブジェクトで追加します。
// Disbable Default Logging
OperationContext.DefaultLogLevel = LogLevel.Off;
// Configure a context to track my upload and set logging level to verbose
OperationContext myContext = new OperationContext() { LogLevel = LogLevel.Verbose };
blobRef.UploadFromStream(stream, myContext);
新しい Blob API
リリース 2.1 では、クライアントからのフィードバックを反映して、新たに Blob テキスト、ファイル、バイト配列の各 API が追加されました。さらに、新しい Blob ストリーム API では、Blob ストリームのオープン、フラッシュ、コミットを非同期で実行できるようになりました。
新しい範囲ベースのオーバーロード
リリース 2.1 では、Blob のアップロード API に新しいオーバーロードが追加されました。これを使用すると、クライアントは指定した範囲のバイト配列やストリームのみを Blob にアップロードできます。この機能により、ストレージ サービスにデータをアップロードする前に、クライアントがそのデータを事前にバッファーすることを回避できます。さらに、ストリームとバイト配列の両方に、新たにダウンロード範囲の API が追加されました。これにより、クライアント側でデータをバッファーしなくても、特定範囲のダウンロードをフォールト トレラントに実行できます。
IgnorePropertyAttribute
POCO オブジェクトを Windows Azure テーブルに保持するときに、特定のクライアントに依存するプロパティを省略する場合があります。今回のリリースで導入された IgnorePropertyAttribute を使用すると、エンティティのシリアル化および逆シリアル化の際にクライアントが特定のプロパティを無視するように、簡単に指定できます。次のスニペットは、IgnorePropertyAttribute を使用して、エンティティの FirstName プロパティを無視する方法を示しています。
public class Customer : TableEntity
{
[IgnoreProperty]
public string FirstName { get; set; }
}
コンパイル済みシリアライザー
POCO 型を取り扱っている場合、以前のリリースの SDK では、実行時のシリアル化および逆シリアル化に適用可能なすべてのプロパティを検出するときに、リフレクションを使用していました。この処理は繰り返し実行されるもので、コンピューティング料金を引き上げる原因となっていました。今回のリリース 2.1 ではコンパイル済みの式が新たにサポートされ、クライアントが実行時に特定の型に対して LINQ 式を動的に生成できるようになりました。これにより、クライアントはリフレクション処理を 1 回だけ行い、ラムダのコンパイルを実行時に行います。特定のエンティティ型に対するその後の読み書きは、すべてこれにより処理されます。パフォーマンスのマイクロベンチマークの結果、この手法では、リフレクション ベースの手法と比較して約 40 倍の計算速度が達成されました。
読み書き処理用にコンパイルされた式はすべて、TableEntity の静的な同時実行辞書に保持されます。この機能を無効にする場合は、TableEntity.DisableCompiledSerializers = true; と指定するだけです。
サードパーティのオブジェクトを簡単にシリアル化
フレームワーク オブジェクトやサードパーティのライブラリのオブジェクトなど、ソースを制御しないオブジェクトのシリアル化をクライアントで実行する場合があります。前のリリースのクライアントでは、シリアル化する型ごとに、独自のシリアル化ロジックを作成する必要がありました。今回のリリース 2.1 では、静的な TableEntity.[Read|Write]UserObject メソッドを使用した CLR 型のシリアル化ロジックおよび逆シリアル化ロジックの基礎を公開しています。これにより、クライアントでの TableEntity から派生しない型のエンティティ オブジェクトの保持やリード バック、および ITableEntity インターフェイスの実装が簡単になりました。また、クライアントでエンティティの型を 2 つとも保持する必要がなく、また双方をマーシャリングする必要もないため、このパターンは DTO 型でサービスを公開する場合に特に便利です。
パフォーマンス向上へのさまざまな取り組み
現在特に力を入れているパフォーマンス向上への取り組みの一環として、Blob の並列アップロード、テーブル サービス レイヤー、Blob の書き込みストリームなど、各種 API でさまざまなパフォーマンス向上を実施しました。パフォーマンス向上に関する詳細な分析結果は、後日ブログでご紹介する予定です。
Windows Phone
Windows Phone クライアントのソース コードは、デスクトップ クライアントと同一のものを基礎としています。しかし、プラットフォームの制限により、重要な相違点が 2 つあります。1 つめは、Windows Phone のライブラリでは、アプリケーションの高速でスムーズな動作を確保するために、同期メソッドが公開されていないという点です。2 つめは、Windows Phone ライブラリでは、プラットフォームでの MD5 の実装が公開されていないため、MD5 をサポートしていないという点です。このため、MD5 を使用する場合は、アプリケーション レイヤーで MD5 の検証を実施する必要があります。現在、Windows Phone ライブラリでテストを実施中で、近日中に結果をお知らせできる予定です。ただし、これは Windows Phone 8 のみを対象としたもので、Windows Phone 7.x とは互換性がありませんのでご注意ください。
まとめ
マイクロソフトでは、このリリースのストレージ クライアント ライブラリの改善に向けて多大な労力を注いできました。皆様からのフィードバックをお待ちしておりますので、ぜひ下部のコメント欄、フォーラム、または GitHub までご意見をお寄せください。
Joe Giardino
参考資料
Windows Azure ストレージを最大限に活用する – TechEd NA ‘13 (英語)
Nuget (英語)
Github (英語)