asp.net-mvc - CLRThreadPoolQueue 中的大部分请求

标签 asp.net-mvc performance azure signalr azure-web-app-service

我们有一个托管在 azure 应用服务中的 ASP.NET MVC 应用程序。运行探查器来帮助诊断可能的缓慢请求后,我们惊讶地发现:

Profiler Result

Slow Requests

CLRThreadPoolQueue 中缓慢请求的百分比异常高。现在,我们已经运行了多个配置文件 session ,每个 session 返回的 CLRThreadPoolQueue 中的资源量都在 40-80% 之间(这是我们在之前的配置文件中从未见过的)。 CPU 每次都低于 40%,在检查我们的指标后,我们没有遇到请求突然激增的情况。

列出的大多数慢速请求都是 super 简单的 API 调用。我们添加了响应缓存并使它们异步。他们唯一做的就是访问数据库寻找单个记录结果。我们检查了数据库的指标,查询平均运行时间约为 50 毫秒或更短。查看这些请求的应用程序见解证实了这一点,并显示数据库查询直到请求时间线的最后才发生(我假设这是队列中的请求)。

最近我们开始将 SignalR 纳入我们应用程序的一部分。它尚未完全使用,但已在代码库中。此后,我们改用 Azure SignalR 服务,但没有看到任何变化。添加 SignalR 是我们自遇到此问题以来所做的唯一“重大”更改/添加。

我知道我们可以扩大和/或增加 minWorkerThreads。然而,这感觉就像我只是治标不治本。

我们尝试过的事情:

  • 查找最频繁的请求并使它们异步(以前不是)
  • 对频繁请求的响应缓存
  • 使用 Azure SignalR 服务,而不是将其托管在同一网络上
  • 运行内存转储并联系 azure 支持(他们 什么也没找到)。
  • 扩展到 S3
  • 使用和不使用线程报告进行分析

-- 这些步骤都没有解决我们的问题 --

我们如何确定哪些请求和/或代码导致请求堆积在 CLRThreadPoolQueue 中?

最佳答案

我们遇到了类似的问题,我猜 SignalR 内部一定使用了大量线程或其他一些竞争资源。

我们做了三件很有帮助的事情:

  1. 在应用启动时调用 ThreadPool.SetMinThreads(400, 1) 以确保线程池有足够的线程来处理从一开始的所有传入请求

  2. 创建第二个应用服务并部署相同的代码。在 javascript 中,将 SignalR URL 设置为指向第二个实例。这样,所有 SignalR 请求都会发送到一个应用程序服务,而应用程序的所有 HTTP 请求都会发送到另一个应用程序服务。显然,这需要设置 SignalR 背板,但假设您的应用服务有超过 1 个实例,您无论如何都必须执行此操作

  3. 检查任何同步代码路径的代码(例如,对数据库或 API 进行非异步调用)并将其转换为异步代码路径

关于asp.net-mvc - CLRThreadPoolQueue 中的大部分请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60402708/

相关文章:

performance - 在矩阵中找到长度为 N 的最大成本路径的算法,从 [0,0] 到最后一行

Python mmap 对象提示 Python 3.5.2 上的字符串模式(不在 Python 2.6.6 中)

Azure Web App - 将具有自定义域的生产槽备份恢复到部署槽

azure - 自动缩放连续 Azure WebJobs 不起作用

c# - 使用属性和约定路由

javascript - 对 ASP.NET MVC Controller 的 JQuery JSON POST 请求未到达端点,但手动使用路由工作正常

c# - 将 Razor .cshtml 文件转换为 C# .cs 文件

c# - 一般使用 asp.net mvc 模型绑定(bind)器

c# - 使用约束连接多个 IEnumerable

azure - 禁用在发布设置上将诊断数据发送到应用程序见解