2

我只在我的本地工作站和产品服务器上收到此错误。在 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 的内存分配?

4

0 回答 0