我工作的应用程序已经投入生产多年,但是在UI(ASP WebForms)和服务(WCF)之间的应用越来越频繁。自推出以来,用户数量和数据量都大幅增加。
最初,我们将问题归结为表现不佳的SQL Server群集(服务使用的群集),并迁移到功能更强大的群集。但是,问题仍然存在,而且我们每天收到的超时数量似乎也在增加。
我们已聘请我们的DBA,但无法隔离SQL Server上的瓶颈。我还通过测试控制台应用程序直接调用服务来执行测试,问题也出现在那里,导致我认为问题不在于WebForms,而在于WCF服务。
我对如何解决这个理论(并开始解决它)感到茫然,因为它只出现在看似高流量的情况下。
是否存在WCF和可扩展性的已知问题,或者当前服务实施是否有可能存在缺陷?
答案 0 :(得分:1)
我怀疑这个问题与SQL服务器和Application层之间的交互有关。我将假设您没有在您的应用程序中使用APM,因为您没有提及它。更不用说,在大多数人看来,APM是为了让UI工作更快,对吗?
科学位,专注
ASP.Net/IIS默认为您提供有限数量的线程。记住线程是昂贵的,每个线程占用调度程序时间并以各种堆栈的形式占用内存和什么不是。这几乎是世界上所有计算机的缺陷。
在.net中,所有工作都在线程上完成。因此,当没有空闲线程时,IIS会将请求放入队列以等待线程。现在,通常你会想到如果所有线程都在使用中,我们就会有很高的CPU利用率。这是错的。通常使用现代CPU,大多数时候它们都处于I / O状态,这意味着它们正在睡觉。
在这种情况下,通常发生的是一些请求进来。他们自己的线程每次踢,然后命中数据库。然后他们等待(睡觉)。您的CPU util值达到0%,而所有线程都在使用中。更多请求进来。它们被放入队列中。数据库请求返回,一些请求出列(但不是全部)。然后队列上的请求超时。
Moar Thread!
我们如何解决这个问题?显然,我们希望尽可能快地从IIS队列中获取尽可能多的工作,然后进入SQL服务器,对吧?显然答案是增加线程数,对吗?现在,正如我之前提到的,线程很昂贵,所以如果你有一个功能强大的SQL服务器,你的应用服务器仍然会在SQL服务器之前放弃幽灵,同时仍然拥有0%的CPU工具。显然,更多的线程不会让我们到达我们想要的地方。
Async / await magic sauce!
接受的解决方案是实际使用异步编程。
但不是异步/等待UI和并行化吗?
没有。它最常见于UI和并行化,因为它的收益最容易想象。在1小时的演示中模拟1M点击/秒服务要困难得多。
因此,当我们向数据库发送查询时,线程会跳回IIS队列以服务下一个客户,而不是在结果上休眠。当结果返回时,通知下一个可用线程并处理它。
因此,使用async / await进行数据库调用,可以最大化CPU /网络util并忽略数据库的延迟。实际上,您会发现应该将瓶颈转移到SQL服务器上。
但我的API在哪里?
啊......这就是问题所在。 Async / Await非常新鲜。你需要VS 2012和.net 4.5(以及sorta)才能使用它。此外,大多数数据库API还没有完全支持Async / Await。例如Entity Framework,Microsoft的旗舰数据库技术仅支持EF 6.0 ALPHA中的async / await(编写本文时),并且很可能只支持MS SQL SERVER。