如何提高 ASP.Net Web 服务性能
How to Improve ASP.Net Web Service performance
我们的应用程序中有一个旧的 ASP.Net asmx web 服务,它有时会接收批量请求。单个请求的服务时间不到 5 秒。但是当它收到 20 个或更多的并发请求时,需要一分钟多的时间。下面是它的实现方式,
1) 从外部客户端接收带有输入数据的请求
2)验证后根据输入数据从数据库中获取20种可能性
3) 然后它将使用 foreach 迭代所有 20 种可能性,并根据可能性数据从其他外部服务或数据库中获取解决方案。在旧的实现中,我们使用 Parallel.Foreach 并行执行所有 20 个调用(服务调用或数据库调用)以提高性能。
4)之后服务会将所有20个解决方案发回给客户端。
考虑到需要 2-3 秒的外部服务调用,这种旧方法适用于少数(1 或 2)个请求并且 asmx 服务的响应时间非常快(不到 5 秒)。但是这种方法正在当并发请求数超过 20.Concurrent 请求时超过 60 秒,根据专家分析,请求将 CPU 利用率推至 100% 和线程池饥饿,并导致请求排队等待线程分配。
所以我们得到了一个建议,用 async/await 实现从头到尾替换并行扩展和完整服务 end.I 已经实现了 async/await 端到端并且还替换了 Parallel.foreach在 TPL 中有 Task.WhenAll。但是在这个 implementation.for 单个请求 20 秒之后响应时间增加了很多,批量请求需要 2 分钟以上。
我也尝试使用 async foreach 代替下面文章中提到的 parallel.foreach,但性能仍然很差。
根据日志,基本问题是外部服务 calls/DB 在旧并行或新并行中调用 foreach async/await implementations.But 这些服务响应对于单个请求非常快。与并行扩展实施相比,异步实施在完成服务调用方面花费的时间更多。
如果单个请求少于 5 秒,我认为批量请求的服务时间不应超过 20 秒。
任何人都可以请我提高性能的前进方向是什么?
提前致谢。
此致,
拉古。
看起来这里同时发生了很多事情。我相信你有导致许多副作用的潜在问题。
我会假设您的服务器在 CPU 和内存方面足以处理并发连接(尽管 CPU 100% 让我感到奇怪)。
在我看来,您的问题是并行任务(或线程)竞争相同的资源。这可以解释为什么多个请求需要更多时间以及为什么异步范例需要更多时间。
让我解释一下:
实践中的问题
并行实现:1个或2个请求需要最少的同步,所以即使它们竞争相同的资源也应该没问题。
当 20 个线程尝试访问相同的资源时,会发生很多事情,您会遇到一种称为活锁的情况。
当您切换到异步时,没有请求等待线程(它们正在等待 IO 线程),因此您使问题变得更糟。
(我怀疑是你数据库的问题,如果你的数据库服务器是同一台机器的话,也能说明利用率)
解决方案
与其尝试提高并行度,不如找到有争议的资源并找出问题所在。
如果它在您的数据库中(最可能的情况),那么您需要确定导致问题的查询并修复它们(索引、统计信息、查询计划等等)。显示锁和查询执行计划的数据库分析器是你的朋友。
如果问题出在您的代码中,请尽量减少竞争条件并改进您的算法。
要获得查找位置的提示,请使用 Visual Studio 分析工具:https://docs.microsoft.com/en-us/visualstudio/profiling/profiling-feature-tour?view=vs-2019 或任何外部 .net 分析软件。
我们的应用程序中有一个旧的 ASP.Net asmx web 服务,它有时会接收批量请求。单个请求的服务时间不到 5 秒。但是当它收到 20 个或更多的并发请求时,需要一分钟多的时间。下面是它的实现方式,
1) 从外部客户端接收带有输入数据的请求
2)验证后根据输入数据从数据库中获取20种可能性
3) 然后它将使用 foreach 迭代所有 20 种可能性,并根据可能性数据从其他外部服务或数据库中获取解决方案。在旧的实现中,我们使用 Parallel.Foreach 并行执行所有 20 个调用(服务调用或数据库调用)以提高性能。
4)之后服务会将所有20个解决方案发回给客户端。
考虑到需要 2-3 秒的外部服务调用,这种旧方法适用于少数(1 或 2)个请求并且 asmx 服务的响应时间非常快(不到 5 秒)。但是这种方法正在当并发请求数超过 20.Concurrent 请求时超过 60 秒,根据专家分析,请求将 CPU 利用率推至 100% 和线程池饥饿,并导致请求排队等待线程分配。
所以我们得到了一个建议,用 async/await 实现从头到尾替换并行扩展和完整服务 end.I 已经实现了 async/await 端到端并且还替换了 Parallel.foreach在 TPL 中有 Task.WhenAll。但是在这个 implementation.for 单个请求 20 秒之后响应时间增加了很多,批量请求需要 2 分钟以上。
我也尝试使用 async foreach 代替下面文章中提到的 parallel.foreach,但性能仍然很差。
根据日志,基本问题是外部服务 calls/DB 在旧并行或新并行中调用 foreach async/await implementations.But 这些服务响应对于单个请求非常快。与并行扩展实施相比,异步实施在完成服务调用方面花费的时间更多。
如果单个请求少于 5 秒,我认为批量请求的服务时间不应超过 20 秒。
任何人都可以请我提高性能的前进方向是什么?
提前致谢。
此致,
拉古。
看起来这里同时发生了很多事情。我相信你有导致许多副作用的潜在问题。
我会假设您的服务器在 CPU 和内存方面足以处理并发连接(尽管 CPU 100% 让我感到奇怪)。
在我看来,您的问题是并行任务(或线程)竞争相同的资源。这可以解释为什么多个请求需要更多时间以及为什么异步范例需要更多时间。
让我解释一下:
实践中的问题
并行实现:1个或2个请求需要最少的同步,所以即使它们竞争相同的资源也应该没问题。
当 20 个线程尝试访问相同的资源时,会发生很多事情,您会遇到一种称为活锁的情况。
当您切换到异步时,没有请求等待线程(它们正在等待 IO 线程),因此您使问题变得更糟。
(我怀疑是你数据库的问题,如果你的数据库服务器是同一台机器的话,也能说明利用率)
解决方案
与其尝试提高并行度,不如找到有争议的资源并找出问题所在。
如果它在您的数据库中(最可能的情况),那么您需要确定导致问题的查询并修复它们(索引、统计信息、查询计划等等)。显示锁和查询执行计划的数据库分析器是你的朋友。
如果问题出在您的代码中,请尽量减少竞争条件并改进您的算法。
要获得查找位置的提示,请使用 Visual Studio 分析工具:https://docs.microsoft.com/en-us/visualstudio/profiling/profiling-feature-tour?view=vs-2019 或任何外部 .net 分析软件。