ファイルのアップロードを受け入れ、そのファイルを別の HTTP エンドポイントに転送する必要がある ASP.NET Web API アプリケーションを作成しています。
多くのユーザーがそれぞれ 100 MB のファイルをアップロードしようとすると (これは有効な使用例です)、アプリケーションのメモリ フットプリントが大きくなり、大きなリクエストの量によってはフットプリントが大きくなりすぎて、アプリケーションがクラッシュして停止してしまうのではないかと懸念しています。
理想的には、Web サーバーがファイルを受信し始めるとすぐに、他の HTTP エンドポイントへのファイルのストリーミングを開始して、サーバーの負荷を大幅に軽減したいと思います。
このプロセスには名前があるはずですが、私はそれを知りません。そのため、検索するのはかなり困難です。
私は Web API でレスポンス ストリーミングに関する作業をかなり行ってきました。しかし、これまでリクエスト ストリーミングを考慮する必要はありませんでした。
私が知る限り、次の方法を検討する必要があります。
- アップロードが完了する前にストリームの処理を開始します。
- HttpClient を使用して同じリクエストをストリーミングし、同じデータを他の HTTP エンドポイントにストリーミングします。
誰か私に何かアドバイスをくれませんか?
ベストアンサー1
興味深い質問ですね。一般的なアドバイスをできるだけ提供できるように努めたいと思います。
考慮すべき点がいくつかあります:
1)Web API はデフォルトでリクエストをバッファリングするため、メモリ使用量がかなり大きくなるのではないかという懸念は当然です。Web API を強制的にストリーム モードでリクエストを処理するようにすることができます。
public class NoBufferPolicySelector : WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
var context = hostContext as HttpContextBase;
if (context != null)
{
if (string.Equals(context.Request.RequestContext.RouteData.Values["controller"].ToString(), "uploading", StringComparison.InvariantCultureIgnoreCase))
return false;
}
return true;
}
public override bool UseBufferedOutputStream(HttpResponseMessage response)
{
return base.UseBufferedOutputStream(response);
}
}
次に、サービスを置き換えます。
GlobalConfiguration.Configuration.Services.Replace(typeof(IHostBufferPolicySelector), new NoBufferPolicySelector());
現時点では WebHost と SelfHost の違いにより、このような変更は WebHost でのみ可能であることに注意してください。エンドポイントが selfHost の場合は、GlobalConfig レベルでストリーミング モードを設定する必要があります。
//requests only
selfHostConf.TransferMode = TransferMode.StreamedRequest;
//responses only
selfHostConf.TransferMode = TransferMode.StreamedResponse;
//both
selfHostConf.TransferMode = TransferMode.Streamed;
以前、Web API で大きなファイルを扱うことについて詳細にブログに書きました。http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/役に立つと思います。
2)次に、 を使用する場合HttpClient
、.NET 4 ではデフォルトでリクエスト本体がバッファリングされるため、実際には .NEt 4.5 を使用する必要があります。
.NET 4 を使用する必要がある場合は、直接操作する必要がありますHttWebRequest
: -http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowreadstreambuffering.aspx-http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowwritestreambuffering.aspx
3)データをクライアントにプッシュすることに関しては、それを実行したい場合は間違いなく可能ですPushStreamContent
。Henrik はここで短い紹介記事を書いています -http://blogs.msdn.com/b/henrikn/archive/2012/04/23/using-cookies-with-asp-net-web-api.aspx(Web API RCビットに基づいているため、署名などを調整する必要があるかもしれません) また、ストリームデータのチャンクをプッシュすることについては、こちらでブログに書きました -http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/
編集:PushStreamContent
リクエスト内の例を確認するには、このサンプルソリューションを参照してください。http://aspnet.codeplex.com/SourceControl/changeset/view/bb167f0b0013#Samples/Net45/CS/WebApi/UploadXDocumentSample/ReadMe.txt