ASP.NET Core 2.2 kestrel 服务器的性能问题
ASP.NET Core 2.2 kestrel server's performance issue
我遇到了 kestrel 服务器的性能问题。我有以下场景:
TestClient(JMeter) -> DemoAPI-1(Kestrel) -> DemoAPI-2(IIS)
我正在尝试创建一个示例应用程序,它可以在请求时获取文件内容。
TestClient(100 Threads) 请求 DemoAPI-1,DemoAPI-1 又请求 DemoAPI-2。 DemoAPI-2 读取一个固定的 XML 文件(最大 1 MB)并且 returns 它的内容作为响应(在生产中 DemoAPI-2 不会被暴露到外面的世界)。
当我测试从 TestClient -> DemoAPI-2 的直接访问时,我得到了以下预期结果(良好):
- 平均:368 毫秒
- 最小值:40 毫秒
- 最大:1056 毫秒
- 吞吐量:40.1/秒
但是当我尝试通过 DemoAPI-1 访问它时,我得到了以下结果:
- 平均:48232 毫秒
- 最小值:21095 毫秒
- 最大值:49377 毫秒
- 吞吐量:2.0/秒
如您所见,有一个巨大的 difference.I 甚至没有获得 DemoAPI-2 的 10% 吞吐量。有人告诉我,与传统的 IIS 相比,kestrel 更高效、更快速。也因为直接访问没有问题,我想我们可以排除DemoAPI-2.
上出现问题的可能
※演示代码API-1 :
string base64Encoded = null;
var request = new HttpRequestMessage(HttpMethod.Get, url);
var response = await this.httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
if (response.StatusCode.Equals(HttpStatusCode.OK))
{
var content = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
base64Encoded = Convert.ToBase64String(content);
}
return base64Encoded;
※演示代码API-2 :
[HttpGet("Demo2")]
public async Task<IActionResult> Demo2Async(int wait)
{
try
{
if (wait > 0)
{
await Task.Delay(wait);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), "test.xml");
var file = System.IO.File.ReadAllText(path);
return Content(file);
}
catch (System.Exception ex)
{
return StatusCode(500, ex.Message);
}
}
一些附加信息:
- 两个 API 都是异步的。
- 两个 API 都托管在不同的 EC2 实例上(C5.xlarge Windows Server 2016)。
- DemoAPI-1(kestrel) 是一个独立的API(没有反向代理)
- 为此测试将 TestClient(jMeter) 设置为 100 个线程。
- 目前还没有对 kestrel 服务器进行其他配置。
- 目前还没有可能影响性能的操作过滤器、中间件或日志记录。
- 通信是在 5001 端口上使用 SSL 完成的。
- 演示的等待参数API2 目前设置为 0。
- DEMOAPI-1的CPU使用率不超过40%。
DEMOAPI-1 执行 non-asynchronous 流读取:
var bytes = stream.Read(read, 0, DataChunkSize);
while (bytes > 0)
{
buffer += System.Text.Encoding.UTF8.GetString(read, 0, bytes);
// Replace with ReadAsync
bytes = stream.Read(read, 0, DataChunkSize);
}
这可能是很多请求的吞吐量问题。
此外,我不完全明白您为什么不使用 IIS 和 Kestrel 测试相同的代码,我认为您只需要更改环境而不是代码。
问题是由于HttpClient 的端口耗尽问题。
我能够通过使用 IHttpClientFactory 来解决这个问题。
以下文章可能会对遇到类似问题的人有所帮助。
我遇到了 kestrel 服务器的性能问题。我有以下场景:
TestClient(JMeter) -> DemoAPI-1(Kestrel) -> DemoAPI-2(IIS)
我正在尝试创建一个示例应用程序,它可以在请求时获取文件内容。 TestClient(100 Threads) 请求 DemoAPI-1,DemoAPI-1 又请求 DemoAPI-2。 DemoAPI-2 读取一个固定的 XML 文件(最大 1 MB)并且 returns 它的内容作为响应(在生产中 DemoAPI-2 不会被暴露到外面的世界)。
当我测试从 TestClient -> DemoAPI-2 的直接访问时,我得到了以下预期结果(良好):
- 平均:368 毫秒
- 最小值:40 毫秒
- 最大:1056 毫秒
- 吞吐量:40.1/秒
但是当我尝试通过 DemoAPI-1 访问它时,我得到了以下结果:
- 平均:48232 毫秒
- 最小值:21095 毫秒
- 最大值:49377 毫秒
- 吞吐量:2.0/秒
如您所见,有一个巨大的 difference.I 甚至没有获得 DemoAPI-2 的 10% 吞吐量。有人告诉我,与传统的 IIS 相比,kestrel 更高效、更快速。也因为直接访问没有问题,我想我们可以排除DemoAPI-2.
上出现问题的可能※演示代码API-1 :
string base64Encoded = null;
var request = new HttpRequestMessage(HttpMethod.Get, url);
var response = await this.httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
if (response.StatusCode.Equals(HttpStatusCode.OK))
{
var content = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
base64Encoded = Convert.ToBase64String(content);
}
return base64Encoded;
※演示代码API-2 :
[HttpGet("Demo2")]
public async Task<IActionResult> Demo2Async(int wait)
{
try
{
if (wait > 0)
{
await Task.Delay(wait);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), "test.xml");
var file = System.IO.File.ReadAllText(path);
return Content(file);
}
catch (System.Exception ex)
{
return StatusCode(500, ex.Message);
}
}
一些附加信息:
- 两个 API 都是异步的。
- 两个 API 都托管在不同的 EC2 实例上(C5.xlarge Windows Server 2016)。
- DemoAPI-1(kestrel) 是一个独立的API(没有反向代理)
- 为此测试将 TestClient(jMeter) 设置为 100 个线程。
- 目前还没有对 kestrel 服务器进行其他配置。
- 目前还没有可能影响性能的操作过滤器、中间件或日志记录。
- 通信是在 5001 端口上使用 SSL 完成的。
- 演示的等待参数API2 目前设置为 0。
- DEMOAPI-1的CPU使用率不超过40%。
DEMOAPI-1 执行 non-asynchronous 流读取:
var bytes = stream.Read(read, 0, DataChunkSize);
while (bytes > 0)
{
buffer += System.Text.Encoding.UTF8.GetString(read, 0, bytes);
// Replace with ReadAsync
bytes = stream.Read(read, 0, DataChunkSize);
}
这可能是很多请求的吞吐量问题。
此外,我不完全明白您为什么不使用 IIS 和 Kestrel 测试相同的代码,我认为您只需要更改环境而不是代码。
问题是由于HttpClient 的端口耗尽问题。 我能够通过使用 IHttpClientFactory 来解决这个问题。 以下文章可能会对遇到类似问题的人有所帮助。