私は特定のプロジェクト用の単純なアーキテクチャを持っています。これは次のようになります。
- ユーザーが ASP.NET MVC を使用してファイルを要求する
- 上記のファイルのローカル キャッシュがチェックされ、キャッシュに存在しない場合、ファイルは Azure Blob ストレージからプルされます。
- この時点で、ファイルは間違いなくサーバー上にあり、パスがわかります。
- サードパーティのライブラリを使用してファイルを開き、パスを指定すると、ユーザーのビューを作成するために使用するクラス構造が返されます。
これは、99% の確率で機能します。ファイルはキャッシュで見つかるかダウンロードされ、サードパーティのコードを使用して開かれた後、Nice ビューでユーザーに表示されます。
ただし、複製できる奇妙な状況があり、実稼働サーバーが完全にクラッシュします。
それらは次のとおりです。
- ファイルがキャッシュにありません
- ファイルは Azure からダウンロードされます
- ファイルを開くときにサードパーティの (安全でない) ライブラリがクラッシュする
- サーバーを持っていきます。
安全でないライブラリを使用してトラブルを起こしていることは理解していますが、最も奇妙なのは、Azure が最初に正しく使用され、Azure がヒットしなかったため、2 回目の試行でファイルがキャッシュされていることです。ファイルは正常に開きます。
サード パーティのライブラリは、基本的に Azure からダウンロードしたファイルが破損していると見なしますが、まったく同じコードが Azure の関与なしにまったく同じファイルを開こうとしても、問題なく開きます。
そのため、最初は Azure のせいにしました。ファイルを正しく閉じていなかったのかもしれません。私はチェックしましたが、ファイルを取得するために使用するファイルストリームは間違いなく閉じられています(usingステートメントでラップされています)。
コードは以下のとおりです (forceRefresh は、常にローカル キャッシュをスキップするように設定できるフラグです)。パスはサーバー上の場所に設定されています ~/tmp
if (!File.Exists(path) || forceRefresh)
{
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
ICloudBlob blob = blobContainer.GetBlockBlobReference("myblob");
using (var filestream = new FileStream(path,FileMode.Create,FileAccess.ReadWrite,FileShare.Read))
{
blob.DownloadToStream(filestream);
}
}
さらに奇妙なことに、テストを繰り返しました。今回は、クラッシュの後、キャッシュからファイルを削除して、Azure が再びヒットするようにしました。そうであり、クラッシュを引き起こすことなくファイルが開きます。
そのため、Azure からダウンロードしたファイルを初めて開いたときにのみ発生するようです。アプリケーション プールをリサイクルするだけで、必要に応じてエラーを発生させることができます。
これをデバッグする方法について何か提案はありますか? ローカルの開発マシンでレプリケートできません。
編集: Richard Turner からのフィードバックへの回答
ブロブ取得コードが例外の原因であるとは思いません。これは、Web アプリがクラッシュした場合、ファイルがダウンロードされた後であるためです。その後の再試行でファイルを開くことができるため、ファイルが破損していないことを確認することもできます。
「安全でない」に関してあなたが言ったことはまさに正しいです-私はPInvokeを実行するラッパーコードを持っています-しかし、IDisposableを実装していません。これはすぐに調べます。パフォーマンスに関しては、現時点では心配していません。
私のコードの再編成に関して、私が説明する「キャッシュ」は実際にはディスク上のファイルのセットであるため、本質的にはあなたが推奨する構造をすでに持っています。サードパーティのライブラリはファイルパスのみを入力として受け入れるため、そのルートに従う必要がありました。
最後の質問への回答:
ブロブをストリームとして読み取ることは、それを読み取ることができる唯一の方法ですか? それを byte[] などとして取得するための API メソッドは見当たりません。
FileStream は読み取り/書き込みである必要はありませんが、変更しても改善されませんでした。