不可预测的 API 请求延迟峰值出现在我的 ASP.NET Web API 发布到 Azure Web App
Unpredictable API requests latency spikes in my ASP.NET Web API published to Azure Web App
我们有一个生产系统,它是一个发布到 Azure
的 ASP.NET Web API
(经典,而非 .NET Core
)应用程序。数据存储是 Azure SQL Database
,我们使用 Entity Framework
来访问数据。 API 具有中等负载,每秒 10-60 个请求,upper_90
延迟为 100-200 毫秒,这是我们的目标延迟。前段时间,我们注意到我们的服务大约每 20-30 分钟就会停止一次,并且延迟会跳到大约 5-10 秒。所有请求开始变慢大约一分钟,然后系统自行恢复。同时没有请求被丢弃,它们只是需要更长的时间来执行。短时间(通常为 1 分钟)。
我们开始在 HTTP 请求遥测 (Azure) 中看到以下图片:
我们还可以看到与我们的 Azure SQL 数据库指标的相关性,例如 DTU(下降)和连接(增加):
我们分析了服务器,没有发现与主机有任何关联(我们只有一台主机)CPU/Memory 使用率,它稳定在 20-30% CPU 使用率并且50% 的内存使用率。
我们还有另一个遥测来源,它显示了相同的行为。我们的遥测测量 API 延迟和数据库指标,例如活动连接数和池连接数(ADO.NET 连接池):
有趣的是,每个系统停顿都伴随着池连接数量的增加。我们的测试表明,池中的连接越多,您等待来自该池的新连接以执行下一个数据库操作的时间就越长。我们分析了一些建议,但无法证明或反驳其中任何一个:
- ADO.NET 连接泄漏(我们所有的数据库访问都发生在具有正确连接 disposal/return 到池的 using 语句中)
- Socket/Port 耗尽 - 无法正确跟踪该指标的遥测
- CPU/Memory 瓶颈 - 图表显示存在 none
- DTU(数据库单位)瓶颈 - 图表显示存在 none
截至目前,我们正在尝试确定此行为的可能罪魁祸首。不幸的是,由于缺少遥测,我们无法识别导致它的变化,所以现在处理这个问题的唯一方法是正确诊断它。而且,当然,我们只能在永久负载下在生产中重现它(即使负载不高,如每秒 10 个请求)。
此行为的可能原因是什么?诊断和排除故障的正确方法是什么?
可能有以下几种原因:
问题可能出在您的应用程序代码中,请创建暂存环境并使用探查器工具遥测(即使用 YourKit .NET Profiler)重新运行您的测试 - 这将允许您检测最重的方法,最大的对象,最慢的数据库查询,etc.Also 使用 JMeter 对 API 进行负载测试。
我建议您尝试使用 Kudu Process API 查看当前 运行ning 进程的列表,并获取有关它们的更多信息列出它们的 CPU 时间。
如何在 Azure 应用服务中监控 CPU 的文章如下:
https://azure.microsoft.com/en-in/documentation/articles/web-sites-monitor/
https://azure.microsoft.com/en-in/documentation/articles/app-insights-web-monitor-performance/
我们最终将几个托管在单个应用程序服务计划中的 Web 应用程序分开。尽管指标没有向我们显示应用程序 CPU 存在任何瓶颈,但还有其他应用程序会导致 CPU 使用高峰,从而导致连接池队列增长和巨大的延迟高峰。
当我们检查应用服务计划使用情况并将其与数据库计划使用情况进行比较时,很明显瓶颈在应用服务计划中。虽然 CPU 瓶颈导致不均匀的延迟峰值仍然很难解释,但我们决定将负载最重的 Web 应用程序分离到一个单独的计划中,并单独处理它。分离后应用程序正常运行,没有 CPU 或延迟尖峰,它看起来非常稳定(与尖峰之间的图片相同):
我们将继续分析其他应用程序并最终找到罪魁祸首,但此时关键任务网络应用程序处于隔离状态并且非常稳定。这里的教训是不仅要监控 Web 应用程序资源使用情况,还要监控可能有其他应用程序消耗资源(CPU、内存)
的托管应用程序服务计划
我们有一个生产系统,它是一个发布到 Azure
的 ASP.NET Web API
(经典,而非 .NET Core
)应用程序。数据存储是 Azure SQL Database
,我们使用 Entity Framework
来访问数据。 API 具有中等负载,每秒 10-60 个请求,upper_90
延迟为 100-200 毫秒,这是我们的目标延迟。前段时间,我们注意到我们的服务大约每 20-30 分钟就会停止一次,并且延迟会跳到大约 5-10 秒。所有请求开始变慢大约一分钟,然后系统自行恢复。同时没有请求被丢弃,它们只是需要更长的时间来执行。短时间(通常为 1 分钟)。
我们开始在 HTTP 请求遥测 (Azure) 中看到以下图片:
我们还可以看到与我们的 Azure SQL 数据库指标的相关性,例如 DTU(下降)和连接(增加):
我们分析了服务器,没有发现与主机有任何关联(我们只有一台主机)CPU/Memory 使用率,它稳定在 20-30% CPU 使用率并且50% 的内存使用率。
我们还有另一个遥测来源,它显示了相同的行为。我们的遥测测量 API 延迟和数据库指标,例如活动连接数和池连接数(ADO.NET 连接池):
有趣的是,每个系统停顿都伴随着池连接数量的增加。我们的测试表明,池中的连接越多,您等待来自该池的新连接以执行下一个数据库操作的时间就越长。我们分析了一些建议,但无法证明或反驳其中任何一个:
- ADO.NET 连接泄漏(我们所有的数据库访问都发生在具有正确连接 disposal/return 到池的 using 语句中)
- Socket/Port 耗尽 - 无法正确跟踪该指标的遥测
- CPU/Memory 瓶颈 - 图表显示存在 none
- DTU(数据库单位)瓶颈 - 图表显示存在 none
截至目前,我们正在尝试确定此行为的可能罪魁祸首。不幸的是,由于缺少遥测,我们无法识别导致它的变化,所以现在处理这个问题的唯一方法是正确诊断它。而且,当然,我们只能在永久负载下在生产中重现它(即使负载不高,如每秒 10 个请求)。
此行为的可能原因是什么?诊断和排除故障的正确方法是什么?
可能有以下几种原因:
问题可能出在您的应用程序代码中,请创建暂存环境并使用探查器工具遥测(即使用 YourKit .NET Profiler)重新运行您的测试 - 这将允许您检测最重的方法,最大的对象,最慢的数据库查询,etc.Also 使用 JMeter 对 API 进行负载测试。
我建议您尝试使用 Kudu Process API 查看当前 运行ning 进程的列表,并获取有关它们的更多信息列出它们的 CPU 时间。
如何在 Azure 应用服务中监控 CPU 的文章如下:
https://azure.microsoft.com/en-in/documentation/articles/web-sites-monitor/
https://azure.microsoft.com/en-in/documentation/articles/app-insights-web-monitor-performance/
我们最终将几个托管在单个应用程序服务计划中的 Web 应用程序分开。尽管指标没有向我们显示应用程序 CPU 存在任何瓶颈,但还有其他应用程序会导致 CPU 使用高峰,从而导致连接池队列增长和巨大的延迟高峰。
当我们检查应用服务计划使用情况并将其与数据库计划使用情况进行比较时,很明显瓶颈在应用服务计划中。虽然 CPU 瓶颈导致不均匀的延迟峰值仍然很难解释,但我们决定将负载最重的 Web 应用程序分离到一个单独的计划中,并单独处理它。分离后应用程序正常运行,没有 CPU 或延迟尖峰,它看起来非常稳定(与尖峰之间的图片相同):
我们将继续分析其他应用程序并最终找到罪魁祸首,但此时关键任务网络应用程序处于隔离状态并且非常稳定。这里的教训是不仅要监控 Web 应用程序资源使用情况,还要监控可能有其他应用程序消耗资源(CPU、内存)
的托管应用程序服务计划