【发布时间】:2015-11-25 12:51:47
【问题描述】:
一两天前,关于我们在那里运行的 WCF 服务,我们的生产服务器上开始发生一些非常奇怪的事情:似乎 某事 开始将相关进程的 CPU 周期速率限制为 CPU 数量一个核心上可用的周期,即使负载分布在所有核心上(进程没有将一个核心消耗到 100% 使用率)
该服务主要只是一个 CRUD(创建、读取、更新、删除)服务,但存在一些长时间运行(可能需要长达 20 分钟)的服务调用除外。这些长时间运行的服务调用启动一个简单的线程并返回 void,因此不会让客户端应用程序等待或阻止 WCF 连接:
// WCF Service Side
[OperationBehavior]
public void StartLongRunningProcess()
{
Thread workerThread = new Thread(DoWork);
workerThread.Start();
}
private void DoWork()
{
// Call SQL Stored proc
// Write the 100k+ records to new excel spreadsheet
// return (which kills off this thread)
}
在上述调用开始之前,服务似乎做出了应有的响应,快速获取数据以显示在前端。
当您启动长时间运行的进程,并且 CPU 使用率达到 100 / CPUCores 时,前端响应变得越来越慢,最终在几分钟后不再接受任何 WCF 连接。
我认为正在发生的事情是,长时间运行的进程正在使用操作系统允许的所有 CPU 周期,因为某些东西对其进行了速率限制,并且 WCF 无法接受传入的连接,更不用说执行请求。
在某些时候,我开始怀疑我们的虚拟服务器运行的集群是否以某种方式这样做,但后来我们设法在我们的开发机器上重现了这一点,客户端使用环回地址与服务通信,所以硬件防火墙是也不干扰网络流量。
在 VisualStudio 内部对此进行测试时,我设法启动了 4 个这些长时间运行的进程,并通过调试器确认所有 4 个进程都在不同的线程中同时执行(通过检查 Thread.CurrentThread.ManagedThreadId),但仍然只使用 100 / CPUCores 总计 CPU 周期。
在生产服务器上,CPU 使用率不会超过 25%(4 核),当我们将 CPU 核数翻倍至 8 时,CPU 使用率不会超过 12.5%。
我们的开发机器有 8 个核心,CPU 使用率也不会超过 12.5%。
其他值得一提的服务
- 它是一个 Windows 服务
- 它在 TopShelf 主机中运行
- 在部署(我们的服务)后问题并未开始
- 生产服务器正在运行 Windows Server 2008 R2 Datacenter
- 开发机器正在运行 Windows 7 企业版
我们已经检查、仔细检查和尝试过的事情:
- 将进程的优先级从正常更改为高
- 已检查进程的处理器关联性是否不限于特定内核
- [ServiceBehavior] 属性设置为 ConcurrencyMode = ConcurrencyMode.Multiple
- 传入的 WCF 服务调用正在不同的线程上执行
- 从仅在控制台应用程序中托管 WCF 服务的方程式中删除 TopShelf
- 设置 WCF 服务限制值:
关于什么可能导致这种情况的任何想法?
【问题讨论】:
-
想知道您的网站是否用完了应用程序池的线程
-
它不是网站,它是内部应用程序的后端服务
-
哇,您每次都为此创建一个线程?为什么不使用
ThreadPool?它将比您的团队更明智地在内部使用线程。 -
是的,这个电话不会经常被击中,可能一天一两次。 ThreadPool 不是灵丹妙药,它们有自己的位置,而这不是其中之一。
-
极限不太可能。可能,因为您正在写入数据库,所以您是数据库绑定的。向数据库添加更多负载并不会使其运行得更快,这就是添加线程无济于事的原因。加载大量负载,然后暂停调试器。在大多数情况下,您会看到数据库调用中除了一个线程之外的所有线程都停止了。
标签: c# .net multithreading wcf topshelf