我只在我的本地工作站和产品服务器上收到此错误。在 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 api 。
我的 web.config 中有这些
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
<system.web>
<httpRuntime maxRequestLength="2097152" />
</system.web>
我还有一个IHostBufferPolicySelector的实现,它为 PUT 和 POST 请求返回 false。所以对这个 web api 的 PUt & POST 请求没有缓冲。
对于任何 < ~350 MB 的文件,它都可以正常工作。但是当文件大小 >= ~ 400 MB 时,web api 会抛出内存不足异常,并且这只发生在本地工作站和产品服务器上。
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 的内存分配?