【问题标题】:WCF service and time outsWCF 服务和超时
【发布时间】:2013-03-17 19:33:46
【问题描述】:

我开发的一个应用程序已经投入生产多年,但 UI(ASP WebForms)和服务(WCF)之间的超时频率越来越高。自从我们推出以来,用户数量和数据量都显着增加。

最初,我们将问题归咎于性能不佳的 SQL Server 集群(服务使用该集群),然后迁移到功能更强大的集群。但是,问题仍然存在,而且我们每天收到的超时次数似乎还在增加。

我们已经聘请了 DBA,但无法隔离 SQL Server 上的瓶颈。我还通过测试控制台应用程序直接调用服务进行了测试,问题也出现在那里,让我认为问题不在于 WebForms,而在于 WCF 服务。

我不知道如何解决这个理论(并开始解决它),因为它只出现在看似高流量的情况下。

WCF 和可伸缩性是否存在已知问题,或者更有可能是当前的服务实现存在缺陷?

【问题讨论】:

  • 没有更多细节很难给出答案。 WCF 服务使用了哪些类型的绑定?是 SOAP 还是 REST?此外,超时可能表明服务出现问题(即,未处理异常并且客户端超时等待响应)。您是否启用了 WCF 跟踪?
  • @Tim 我们正在使用带有 SOAP 的 BasicHTTPBinding。我会调查追踪。

标签: sql-server performance wcf web-services webforms


【解决方案1】:

我怀疑这个问题与 SQL 服务器和应用程序层之间的交互有关。我将假设您没有在应用程序中使用 APM,因为您没有提及它。更何况,在大多数人看来,APM 是为了让 UI 工作得更快,对吧?

The Science Bit, Concentrate

ASP.Net/IIS 默认为您提供有限数量的线程。请记住线程是昂贵的,每个线程都占用调度程序时间并以各种堆栈的形式占用内存,等等。这几乎是世界上所有计算机的缺陷。

在 .net 中,所有工作都在线程上完成。因此,当没有空闲线程时,IIS 会将请求放入队列以等待线程。现在,通常你会认为如果所有线程都在使用中,那么 CPU 利用率就会很高。这是错误的。通常对于现代 CPU,大部分时间它们都处于 I/O 饥饿状态,这意味着它们处于休眠状态。

在这种情况下,通常会发生一些请求进入。每个线程都踢出自己的线程,然后访问数据库。然后他们等待(睡觉)。您的 CPU 利用率达到 0%,而您的所有线程都在使用中。更多的请求进来。它们被放入队列中。数据库请求返回,一些请求出列(但不是全部)。然后队列中的请求超时。

摩尔线!

我们如何解决这个问题?显然,我们希望尽可能快地将 IIS 队列中的大部分工作转移到 SQL 服务器上,对吗?所以显然答案是增加线程数,对吧?现在,正如我之前提到的,线程很昂贵,所以如果你有一个非常强大的 SQL 服务器,你的应用程序服务器仍然会在 SQL 服务器之前放弃幽灵,同时仍然有 0% 的 CPU 利用率。显然,更多的线程不会让我们到达我们想要的地方。

异步/等待魔法酱!

公认的解决方案是实际使用异步编程。

但不是异步/等待 UI 和并行化吗?

没有。它最常在 UI 和并行化中展示,因为它的收益最容易可视化。在 1 小时的演示中模拟 100 万次点击/秒的服务要困难得多。

因此,当我们向数据库发送查询时,线程不会在结果上休眠,而是跳回 IIS 队列以服务下一个客户。当结果返回时,通知下一个可用线程并处理它。

因此,使用 async/await 进行数据库调用,您可以最大限度地利用 CPU/网络利用率并忽略数据库的延迟。其实你会发现,你应该已经把瓶颈转移到了 SQL server 上。

但是我的 API 在哪里?

啊……问题来了。异步/等待是相当新的。您需要 VS 2012 和 .net 4.5(很好)才能使用它。此外,大多数数据库 API 尚不完全支持 Async/Await。

例如 Entity Framework,微软的旗舰 DB 技术仅支持 EF 6.0 ALPHA 中的 async/await(截至撰写本文时),并且很可能仅支持 MS SQL SERVER。

【讨论】:

  • 感谢您的彻底回复。我很想用异步方法重写服务,但是,我们只在 .NET FX 2 上,重写不在这项工作的范围内。除了额外的线程,您能提出任何其他解决方案吗?
  • 更多线程、更多内存、更多盒子。这将被大量浪费。他们几乎 100% 的时间都在睡觉。问题是一个架构问题。理论上只需要修复数据库访问层。在实践中,消费代码需要匹配它。如果您可以升级到至少 4.0,我有一些建议。但是 2.0/3.5 确实无法让我访问 Microsoft 所做的任何并发工作。
  • @TFerrell 嗯...只是想到了一些可以大大提高性能的事情。一点脑洞都没有。物理地将中间层移近 SQL 层。添加缓存逻辑以减少 SQL 命中。这些可能是您增加可用线程数量的最佳选择。
猜你喜欢
  • 2011-09-01
  • 2012-03-23
  • 2010-09-18
  • 2013-01-15
  • 2011-01-14
  • 2010-10-29
  • 2013-05-12
相关资源
最近更新 更多