繁体   English   中英

ASP.Net Core API 响应花费太多时间

[英]ASP.Net Core API response takes too much time

我有一个包含 9000 行和 97 列的 SQL 数据库表。 它的主键有两列: ColorName 您可以看到简化的表格以更好地形象化:

在此处输入图像描述

我有一个 ASP.NET Core API 监听 URL api/color/{colorName} ,它读取表格以获取颜色信息。 目前我有 3 个 colors,每个大约 3000 行。

这需要太多时间。 它在 2383 毫秒内读取表并在 14 毫秒内映射到 DTO。 之后我立即将 DTO 返回给消费者,但不知何故 API 花费了 4135.422 毫秒。 我不明白为什么。 我想我应该花 2407.863 毫秒,但事实并非如此。 它需要将近 2 倍的时间。

您可以在下面看到我的代码和日志。 您知道如何改善响应时间吗?

我使用 Entity Framework Core 3.1、AutoMapper 和 ASP.NET Core 3.1。

服务:

public async Task<IEnumerable<ColorDTO>> GetColors(string requestedColor)
{
    var watch = System.Diagnostics.Stopwatch.StartNew();
    var colors = await _dbContext.Colors.Where(color => color.color == requestedColor).ToListAsync();
    watch.Stop();
    _logger.LogError("Color of:{requestedColor} Reading takes:{elapsedMs}", requestedColor, watch.ElapsedMilliseconds);


    var watch2 = System.Diagnostics.Stopwatch.StartNew();
    var colorDtos = _mapper.Map<IEnumerable<ColorDTO>>(colors);
    watch2.Stop();
    _logger.LogError("Color of:{requestedColor} Mapping takes:{elapsedMs}", requestedColor, watch2.ElapsedMilliseconds);

    return colorDtos;
}

Controller:

public async Task<ActionResult<IEnumerable<ColorDTO>>> GetBlocksOfPanel(string requestedColor)
{
    return Ok(await _colorService.GetColors(requestedColor));
}

和日志:

2020-04-27 15:21:54.8793||0HLVAKLTJO59T:00000003|MyProject.Api.Services.IColorService|INF|Color of Purple Reading takes:2383ms
2020-04-27 15:21:54.8994||0HLVAKLTJO59T:00000003|MyProject.Api.Services.IColorService|INF|Color of Purple Mapping takes:14ms
2020-04-27 15:21:54.9032||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|INF|Executed action method MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 2407.863ms.
2020-04-27 15:21:54.9081||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor|INF|Executing ObjectResult, writing value of type 'System.Collections.Generic.List`1[[MyProject.Api.Contracts.Dtos.ColorDTO, MyProject.Api.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
2020-04-27 15:21:56.4895||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|INF|Executed action MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web) in 4003.8022ms
2020-04-27 15:21:56.4927||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Routing.EndpointMiddleware|INF|Executed endpoint 'MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web)'
2020-04-27 15:21:56.4972||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Hosting.Diagnostics|INF|Request finished in 4135.422ms 200 application/json; charset=utf-8

正如@ejwill 在他的评论中提到的,您需要考虑整个操作中的延迟。 从数据库获取并映射到 DTO 只是请求和响应到 API 的往返过程中发生的事情的一部分。

您可以通过那里的一些优化来减少对数据库表的查询时间。 您没有指出您正在使用什么数据库,但是基于两个字符串/varchar 值的复合键可能不一定是性能最高的,并且对您正在过滤的值使用索引也可能会有所帮助 - 有那里的权衡取决于您是针对写入还是针对读取进行优化。 话虽如此,无论哪种方式,97 列都不是微不足道的。 是否需要查询并返回 API 上的所有 97 列? 分页是一种选择吗?

如果您必须一次返回所有 97 列的所有数据并且经常查询 API,您还可以考虑使用内存缓存,尤其是在表不经常更改的情况下; 您不必每次都往返于数据库,而是在 memory 中保留数据的副本,以便可以更快地返回。 您可以查看支持世代 model 的内存缓存的实现,以便在获取新版本时继续提供数据。

https://github.com/jfbosch/recache

结果的序列化可能需要大量时间。

首先是序列化本身:如果您返回 3k 条记录,则将其序列化为 JSON 或 XML 将花费大量时间。 考虑转向更紧凑的二进制格式。

第二件事是 memory 和 GC。 如果序列化数据量超过 85,000 字节,则该数据的 memory 将在 LOH 上以一个块的形式分配。 这可能需要时间。 您可能会考虑检查您的 LOH 并查找存储在那里的响应数据。 可能的解决方法可能是响应大块数据和使用带有offsetposition的分页类型。

您可以轻松检查序列化是否会导致性能问题:保留对 DB 的调用,但只返回 100-200 行而不是整个结果给客户端,或者返回更少的 object 字段(例如,仅 3 个)。 时间应该减少。

您的问题与 SQL 方有关。 您应该检查列的索引并在执行计划 state 中运行查询以找到瓶颈。 另外,为了提高性能,我建议重写异步 state 中的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM