我们在 C# 中开发了一个 ASP.NET Core 2.0 Web API,通过 Visual Studio 模板创建。
它已经运行多年,我们从未遇到过任何性能问题。直到最近,我们还没有处理过大的 HTTP 请求,所以我们改进了 API 配置以允许大于 2GB 的请求。
我们修改了应用的Web.config如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483647" />
</requestFiltering>
</security>
</system.webServer>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483647"></jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
</configuration>
使用此配置,我们开始能够毫无问题地接收 .NET Web 应用程序默认情况下大于 30MB 的请求,但是,当这些请求超过大约 100 MB 时,应用程序将返回 500 错误。
API由4层组成:
问题是我尝试发送超过 100MB 的数据并且我已经能够验证它们到达第 2 层和第 3 层(第 1 层仅管理用户安全)但是当它们要将数据从第 3 层传递到第 4 层时,应用程序返回 500 错误。
奇怪的是第 3 层和第 4 层是 DLL,它们不是可以配置请求大小限制的 Web 项目。
API 在 Azure 中发布,我们认为这是一个内存问题,但是,通过增加 API 缩放并增加 RAM 和 CPU,同样的问题不断发生。
有没有人遇到过这样的事情?任何可能的解决方案?
提前非常感谢
除了内容长度之外,您还应该检查请求超时的设置,因为它也可能会在 The
500 - error status code
:
增加请求超时在
.UseKestrel(o => { o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10); })
中的
.Build()
之前添加
Program.cs
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseKestrel(o => { o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10); })
.Build();
}
此外,第三方集成可能会超时或限制,具体取决于您存储文件本身的位置和方式。
当你用这种方法上传小文件时它很好。 但是在处理大文件时,您尝试分块上传文件。 以下代码可以作为很好的起点。
[HttpPost]
public ActionResult ReceiveLargeFileInChunks()
{
// Set the size of each chunk in bytes (e.g. 1 MB)
int chunkSize = 1024 * 1024;
// Get the file from the request
HttpPostedFileBase file = Request.Files[0];
// Get the total size of the file
long fileSize = file.ContentLength;
// Get the file name and extension
string fileName = Path.GetFileName(file.FileName);
string fileExtension = Path.GetExtension(fileName);
// Create a buffer to hold each chunk of data
byte[] buffer = new byte[chunkSize];
// Set the total number of bytes received to zero
long totalBytesReceived = 0;
// Open a file stream to write the received data to disk
using (FileStream fileStream = new FileStream(Server.MapPath("~/App_Data/" + fileName), FileMode.Create, FileAccess.Write))
{
// Loop until all data has been received
while (totalBytesReceived < fileSize)
{
// Read a chunk of data from the input stream
int bytesRead = Request.InputStream.Read(buffer, 0, buffer.Length);
// Write the data to the file stream
fileStream.Write(buffer, 0, bytesRead);
// Increment the total number of bytes received
totalBytesReceived += bytesRead;
}
}
// Return a success message to the client
return Content("File uploaded successfully.");
}