如何提高 ASP.Net Web 服务性能
Posted
技术标签:
【中文标题】如何提高 ASP.Net Web 服务性能【英文标题】:How to Improve ASP.Net Web Service performance 【发布时间】:2021-02-22 02:59:16 【问题描述】:我们的应用程序中有一个旧的 ASP.Net asmx Web 服务,它有时会接收批量请求。单个请求的服务时间不到 5 秒。但是当它收到 20 个或更多并发请求时,它需要一分钟多的时间。以下是它的实现方式,
1)接收来自外部客户端输入数据的请求
2)验证后根据输入数据从数据库中获取20种可能性
3) 然后它将使用 foreach 迭代所有 20 种可能性,并根据可能性数据从其他外部服务或数据库中获取解决方案。在旧实现中,我们使用 Parallel.Foreach 并行执行所有 20 个调用(服务调用或 DB 调用)以提高性能。
4) 之后,Service 会将所有 20 个解决方案发回给客户端。
考虑到外部服务调用需要 2-3 秒,这种旧方法适用于少数(1 或 2 个)请求,并且 asmx 服务的响应时间非常快(不到 5 秒)。但这种方法需要的时间超过当并发请求数量超过 20 时,为 60 秒。根据专家分析,并发请求将 CPU 利用率推至 100% 和线程池饥饿,并导致请求排队等待线程分配。
因此,我们建议用端到端的异步/等待实现替换并行扩展和完整的服务。我已经实现了端到端的异步/等待,并且还在 TPL 中用 Task.WhenAll 替换了 Parallel.foreach。但是在这个实现之后响应时间增加了很多。对于单个请求 20 秒,对于批量请求则需要 2 多分钟。
我还尝试使用 async foreach 代替 parallel.foreach,如下文所述,但性能仍然很差。
https://***.com/questions/14673728/run-async-method-8-times-in-parallel/14674239#14674239
根据日志,基本问题是在旧的并行或新的异步/等待实现中,foreach 内部的外部服务调用/数据库调用。但是对于单个请求,这些服务响应非常快。与并行扩展实现相比,异步实现在完成服务调用方面需要更多时间。
如果单个请求少于 5 秒,我认为批量请求的服务时间不应超过 20 秒。
任何人都可以请我在这里提高性能的方法是什么?
提前致谢。
问候,
拉古。
【问题讨论】:
您可以考虑在您的应用和数据库之间添加一个缓存层,假设缓存一些频繁请求的数据与您的应用的功能兼容。 【参考方案1】:看起来很多事情同时在这里发生。我相信你有一个导致许多副作用的核心问题。
我会假设您的服务器在 CPU 和内存方面足以处理并发连接(尽管 CPU 100% 让我感到疑惑)。
在我看来,您的问题是并行任务(或线程)竞争相同的资源。这可以解释为什么多个请求需要更多时间以及为什么异步范式需要更多时间。
让我解释一下:
实践中的问题
并行实现:1或2个请求需要最小同步,所以即使它们竞争相同的资源,也应该没问题。
当 20 个线程尝试访问相同的资源时,会发生很多事情,您会遇到一种称为活锁的情况。
当您切换到异步时,没有请求等待线程(它们正在等待 IO 线程),因此您会使问题变得更糟。
(我怀疑问题出在你的数据库上。如果你的数据库服务器是同一台机器,也会说明利用率)。
解决办法
与其尝试提高并行度,不如找到有争议的资源并找出问题。
如果它在您的数据库中(最可能的情况),那么您需要识别导致问题的查询并修复它们(索引、统计信息、查询计划等等)。显示锁和查询执行计划的数据库分析器是您的朋友。
如果问题出在您的代码中,请尽量减少竞争条件并改进您的算法。
要获得查找位置的提示,请使用 Visual Studio 分析工具:https://docs.microsoft.com/en-us/visualstudio/profiling/profiling-feature-tour?view=vs-2019 或任何外部 .net 分析软件。
【讨论】:
非常感谢您的回复,根据日志,我可以看到有争议的资源主要是外部服务调用和数据库调用。我们需要为每次迭代进行 3-5 次外部服务调用和一次数据库存储过程调用。所有这些调用都需要最长的处理时间,异步大约需要 2 分钟,并行扩展大约需要 1 分钟。但是所有这些外部服务调用和存储过程调用对于单个请求都运行得非常快。 我们还通过在需要的地方建立索引来改进数据库逻辑。因此,我认为外部服务或存储过程中的实际业务逻辑没有问题。除了这些 forach 或每次迭代的并行之外,我的服务实现的其余部分没有其他问题,在这种情况下可以选择什么来提高性能我的服务结束?还是由于外部服务/DB 无法处理多个请求?谢谢 您需要深入解决问题。想象一个在环境事务中锁定一些数据库行的存储过程。现在想象一下,这个首先运行,然后调用一个服务。该服务需要 2 分钟,并且数据库行仍处于锁定状态。无法执行需要相同行的其他调用,并且在 db 级别被阻止。 数据库也有分析器,可以通知您那里发生的块。 我们的数据库存储过程包含非常简单的选择语句,没有任何进一步的业务逻辑。我不能质疑外部服务供应商,因为他们的服务对于单个请求来说非常快。当请求数量更多时,是否有可能无法执行外部服务?正如你提到的,我肯定会为应用程序和数据库运行分析器。非常感谢以上是关于如何提高 ASP.Net Web 服务性能的主要内容,如果未能解决你的问题,请参考以下文章
提高 ASP.NET Web 应用性能的 24 种方法和技巧
提高 ASP.NET Web 应用性能的 24 种方法和技巧(转载)