このエラーは、ローカル ワークステーションと製品サーバーでのみ発生します。Dev と Cert では正常に動作しています。
ローカル ワークステーション - 20 GB メモリ、Win 7 64 ビット、IIS Express、VS 2013
dev、cert & prod - 8 GB メモリ、2008 R2 64 ビット、IIS 7.5
着信要求の本文を取得してストレージ サーバーにアップロードする Web API (.net 4.0) があります。このWebサイトに従ってWeb APIを構成しました。
私はこれらを私のweb.configに持っています
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
<system.web>
<httpRuntime maxRequestLength="2097152" />
</system.web>
PUT および POST 要求に対して false を返すIHostBufferPolicySelectorの実装もあります。そのため、PUt および POST 用のこの Web API へのリクエストはバッファリングされません。
350 MB 未満のファイルの場合、正常に動作しています。ただし、ファイル サイズが 400 MB 以上の場合、Web API はメモリ不足の例外をスローし、これはローカル ワークステーションと Prod サーバーでのみ発生します。
Web API コントローラーは、以下のコードを呼び出して、要求を宛先サーバーにストリーミングします
public async Task<HttpResponseMessage> StoreObjectAsync(Uri namespaceUrl, string userName, string password, string objectName, Stream objectContent, string contentType = "application/octet-stream", IDictionary<string, string> systemMetadata = null)
{
Uri namespaceRootUrl = Utilities.GetNamespaceRootUrl(namespaceUrl);
using (var request = new HttpRequestMessage() { Method = HttpMethod.Put })
{
request.RequestUri = Utilities.CreateRequestUri(namespaceRootUrl, objectName);
request.Content = new StreamContent(objectContent);
request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
HttpResponseMessage response;
response = await this.httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
return response;
}
}
オンラインでいくつかの調査を行った後、このリンクとこのリンクから、.Net 4.0 の HttpClient がリクエスト本文をバッファリングすることを理解しました。その動作のために、メモリ不足の例外がスローされているように見えました。
そのため、今回はHttpWebRequestを使用してコードを以下に変更しました。これを使用して、リクエストをストリーミングするがバッファリングしないように指定することができます。
public async Task<HttpResponseMessage> StoreObjectAsync(Uri namespaceUrl, string userName, string password, string objectName, Stream content, long contentLength, string contentType = "application/octet-stream", IDictionary<string, string> systemMetadata = null)
{
Uri namespaceRootUrl = Utilities.GetHCPNamespaceRootUrl(namespaceUrl);
HttpWebRequest httpWebRequest = ((HttpWebRequest)WebRequest.Create(requestUri));
httpWebRequest.Method = "PUT";
httpWebRequest.KeepAlive = true;
httpWebRequest.AllowWriteStreamBuffering = false;
httpWebRequest.ContentType = contentType;
httpWebRequest.ContentLength = contentLength;
using (Stream requestStream = await httpWebRequest.GetRequestStreamAsync())
{
await content.CopyToAsync(requestStream);
}
var webResponse = await httpWebRequest.GetResponseAsync();
HttpWebResponse httpWebResponse = (HttpWebResponse)webResponse;
Stream httpWebResponseContent = httpWebResponse.GetResponseStream();
HttpResponseMessage response = new HttpResponseMessage()
{
StatusCode = httpWebResponse.StatusCode,
ReasonPhrase = httpWebResponse.StatusDescription,
Content = new StreamContent(httpWebResponseContent)
};
return response;
}
現在、ローカルマシンで正常に動作しています。エラーやメモリ例外なしで、約 1GB のファイルをアップロードできます。まだこれを Prod にプッシュしていません。
しかし、.net 4.0 で HttpClient を使用した同じコードが、Dev サーバーと Cert サーバーでは機能したが、Prod と私のローカルでは機能しなかった理由はまだわかりません。
理解するのを手伝ってください
Dev と Cert で機能した理由を調べる方法は?
この API へのメモリ割り当てに影響するシステム/サーバー構成は何ですか?