web-dev-qa-db-ja.com

WebAPI要求ストリーミングのサポート

ファイルのアップロードを受け入れ、そのファイルを別のHTTPエンドポイントに転送する必要があるASP.NET Web APIアプリケーションを書いています。

多くのユーザーがそれぞれ100MBのファイルをアップロードしようとすると(これは有効なユースケースです)、アプリケーションのメモリフットプリントが大きくなり、大きなリクエストの量によっては、このフットプリントが大きくなり、アプリケーションが不安定になる可能性があります。以上で死ぬ。

理想的には、Webサーバーがファイルの受信を開始したらすぐに、他のHTTPエンドポイントにファイルのストリーミングを開始して、サーバーの負荷を大幅に軽減したいと思います。

このプロセスには名前があるはずですが、わかりません。そのため、検索がかなり難しくなっています。

私はWeb APIでResponse Streamingを使用してかなりの作業を行いましたが、リクエストストリーミングをこれまで検討する必要がありませんでした。

次の方法を考え出す必要があると言えるでしょう。

  • アップロードが完了する前にストリームの処理を開始します。
  • HttpClientを使用して同じリクエストをストリーミングし、同じデータを他のHTTPエンドポイントにストリーミングします。

誰かが私にいくつかの指針を提供できますか?

30
Gavin Osborn

それは興味深い質問です。私はいくつかの一般的な指針を与えるために最善を尽くします。

考慮すべきこと:

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でのみ可能であることに注意してください。エンドポイントがselfHostedの場合、ストリーミングモードを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/非同期ストリーミングビデオ-with-asp-net-web-api /

EDIT:リクエストのPushStreamContentの例を確認するには、このサンプルソリューションを確認してください- http ://aspnet.codeplex.com/SourceControl/changeset/view/bb167f0b0013#Samples/Net45/CS/WebApi/UploadXDocumentSample/ReadMe.txt

42
Filip W