【问题标题】:ASP.NET Core 2.2 kestrel server's performance issueASP.NET Core 2.2 kestrel 服务器的性能问题
【发布时间】:2025-11-26 21:00:01
【问题描述】:

我遇到了红隼服务器的性能问题。我有以下情况:

    TestClient(JMeter) -> DemoAPI-1(Kestrel) -> DemoAPI-2(IIS) 

我正在尝试创建一个示例应用程序,它可以在请求时获取文件内容。 TestClient(100 Threads) 向 DemoAPI-1 请求,后者又向 DemoAPI-2 请求。 DemoAPI-2 读取一个固定的 XML 文件(最大 1 MB)并将其内容作为响应返回(在生产中 DemoAPI-2 不会暴露给外界)。

当我从 TestClient -> DemoAPI-2 测试直接访问时,我得到了预期的结果(良好),如下所示:

  1. 平均:368ms
  2. 最小值:40 毫秒
  3. 最大值:1056ms
  4. 吞吐量:40.1/秒

但是当我尝试通过 DemoAPI-1 访问它时,我得到了以下结果:

  1. 平均:48232ms
  2. 最小值:21095ms
  3. 最大值:49377ms
  4. 吞吐量:2.0/秒

如您所见,两者之间存在巨大差异。我什至没有 DemoAPI-2 的 10% 吞吐量。有人告诉我,与传统的 IIS 相比,红隼更高效、更快速。也因为直接访问没有问题,我想我们可以消除DemoAPI-2上可能出现的问题。

※DemoAPI-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;

※DemoAPI-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);
        }
    }

一些附加信息:

  1. 两个 API 都是异步的。
  2. 这两个 API 都托管在不同的 EC2 实例上 (C5.xlarge Windows Server 2016)。
  3. DemoAPI-1(kestrel) 是一个独立的 API(没有反向代理)
  4. TestClient(jMeter) 设置为 100 线程进行此测试。
  5. 目前尚未对 kestrel 服务器进行其他配置。
  6. 目前还没有可能影响性能的操作过滤器、中间件或日志记录。
  7. 在 5001 端口上使用 SSL 进行通信。
  8. DemoAPI2 的等待参数现在设置为 0。
  9. DEMOAPI-1 的 CPU 使用率不超过 40%。

【问题讨论】:

  • 几乎不可能知道你的瓶颈在哪里,只有你自己才能弄清楚。我建议在本地运行它并使用 dotTrace 之类的东西来查看代码在哪里花费的时间最多。

标签: asynchronous asp.net-core kestrel-http-server


【解决方案1】:

DEMOAPI-1 对流执行非异步读取:

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 测试相同的代码,我认为您只需要进行环境更改而不是代码。

【讨论】:

  • 感谢您指出。两种 API 的用途不同。 DemoAPI-1 是一个跨平台 API,其中 DemoAPI-2 是特定于 Windows 的 API。我不是在比较 Kestrel 与 IIS,我的目标是找出 Kestrel API 如此缓慢的原因并修复它。我添加 DemoAPI-2 的性能指标只是为了证明托管在 IIS 上的文件读取 API 并不慢。
【解决方案2】:

问题是由于 HttpClient 的端口耗尽问题。 我能够通过使用 IHttpClientFactory 解决这个问题。 以下文章可能会对面临类似问题的人有所帮助。

https://www.stevejgordon.co.uk/httpclient-creation-and-disposal-internals-should-i-dispose-of-httpclient

【讨论】:

    最近更新 更多