【发布时间】:2018-10-28 02:58:23
【问题描述】:
有没有办法从 .NET 中获取关于(C# 5 或更高版本,因此是异步/等待后)待执行任务的数量以及类似指标的数据,用于诊断生产服务器发生的问题?
我正在讨论的案例是一个 async-all-the-way-down 系统(例如,一个大型并行套接字服务器,其中每个请求从一开始就异步运行),其中初始任务生成多个任务,每个任务都需要处理时间(或每个启动更多任务),或生成任务,其中一些阻塞(如第三方代码)和一些正常工作的异步。我见过两种情况很难有效诊断:
- 在正常负载下,一切正常,但如果有足够的请求,CPU 会很快跃升至 100%,所有请求完成的速度越来越慢。当负载减少时,CPU 将保持在 100%,直到大部分待处理任务逐渐完成,然后 CPU 降至正常水平。
- 在正常负载下,一切正常,但如果有足够多的请求,则某些请求(所有这些都是正确异步的)根本无法完成或非常缓慢。当负载减轻时,CPU 将保持在 100%,同时它们都被处理,但任务完成率会出现减速带,并在短时间内显着减慢。
我已经尝试为此编写一个简单的测试,但是没有明显的方法来限制执行程序的数量以及我需要创建的测试它的任务数量,这使得解析信息变得非常困难。通过尝试注销调试信息来不干扰测试本身也非常困难。我将继续尝试创建更好的测试用例并在需要时修改我的问题。
根据我对问题和异步任务系统的理解,这两者实际上都是对实际运行任务的执行程序的争用。
发生第一种情况是因为正在创建的任务多于实际完成的任务,在这种情况下,即使在负载高到足以锁定服务之前,挂起任务的计数器也有助于诊断此问题。
第二种情况的发生是因为一组任务运行时间足够长,但随着时间的推移(有足够的负载)所有执行程序最终同时运行这些任务。一旦完成,它就会处理一些任务,很快就会被另一个长期运行的任务取代。在这种情况下,待处理任务计数器以及其他一些指标会很有用。
是否有任何可用的东西,或者是否有一些未记录/hacky 的方法可以将一些代码移植到应用程序中启动的每个任务的开始/结束,以使其注销/测量这些东西并在何时发出警告任务号爆炸了?
【问题讨论】:
-
对于第一种情况,您应该能够在代码中执行此操作。每个请求都必须有一个大的异步调用(这反过来又调用许多方法并跨越许多任务)。你只需要监控那个大方法返回的任务,就可以知道你的系统当前正在处理多少请求,并在那里实现限制。
-
@KevinGosse 实际执行这一大异步调用的代码是第三方,因此不可修改。但更重要的是,这只会告诉我有多少“初始任务”正在运行。但有时初始任务只会启动另一个任务,有时可能会启动一百个任务,因为这取决于正在处理的请求。
-
程序员通常必须付出很多努力才能从处理器中获得所有可以得到的东西,编写可以真正并发执行的代码并不是那么容易。好吧,显然不是你必须解决的问题。故意不充分利用处理器并不是一项功能,您可以在硬件上花更少的钱。你看到它告诉你你必须花更多的钱。这是完全正常的。使用分析器找出效率低下的地方(如果有的话)。
-
@HansPassant 由于高请求负载导致 CPU 使用率普遍增加并不是我的意思。由于代码中的错误(请求产生的任务太多,或者某些任务不应该被阻塞),这种情况可以最大限度地利用你投入的任何数量的硬件。无需等待它在生产中触发然后在生产服务器上对其进行分析(因为它需要比开发服务器上可行的负载更大的负载)来诊断此错误所在的位置,这就是我寻找性能指标的原因。看到待处理任务的数量增加也适用于开发。
-
我不会在生产环境中尝试这样做,但就未记录/骇人听闻的方式而言,请查看 this method 在运行时替换内存中的现有方法实现。您可能可以使用它来处理 Task 方法。过去在类似情况下,我的成功率参差不齐。
标签: c# .net async-await task