什么可以限制我的C#WCF服务上的CPU周期?

Har*_*man 9 .net c# wcf multithreading topshelf

关于我们在那里运行的WCF服务,一两天前在我们的生产服务器上开始发生一些非常奇怪的事情:似乎有些事情开始将有问题的CPU周期限制为一个内核可用的CPU周期量,甚至虽然负载分布在所有核心上(该过程不会将一个核心烧至100%使用)

CPU图

该服务主要只是一个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)
}
Run Code Online (Sandbox Code Playgroud)

在上述呼叫启动之前,服务似乎应该响应,获取数据以快速显示在前端.

当您启动长时间运行的进程,并且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
  • Dev Machines正在运行Windows 7 Enterprise

我们检查,仔细检查和尝试过的事情:

  • 将进程的优先级从正常更改为高
  • 检查处理器对进程的亲和力不限于特定核心
  • [ServiceBehavior]属性设置为ConcurrencyMode = ConcurrencyMode.Multiple
  • 传入的WCF服务调用正在不同的线程上执行
  • 仅在控制台应用程序中从托管WCF服务的等式中删除TopShelf
  • 设置WCF服务限制值:<serviceThrottling maxConcurrentCalls ="1000"maxConcurrentInstances ="1000"maxConcurrentSessions ="1000"/>

关于可能导致这种情况的任何想法?

bik*_*868 1

必须有一个共享资源,一次只允许单个线程访问它。这实际上一次只允许一个线程运行,并准确地创建您所拥有的情况。

处理器关联掩码是将进程限制为单个 CPU 的唯一方法,如果您这样做,您会看到一个 CPU 被固定,而所有其他 CPU 处于空闲状态(这不是您的情况)。

我们使用一种名为 LeanSentry 的工具,它非常擅长识别此类问题。它将自身作为调试器附加到 IIS,并捕获所有正在执行的进程的堆栈转储,然后告诉您大多数线程是否在同一位置被阻塞。有一个免费试用期足以让您弄清楚这一点。