WCF服务停止处理呼叫15秒

时间:2015-07-20 09:54:31

标签: c# multithreading wcf windows-services webhttpbinding

我在我的一个WCF服务中遇到了一个奇怪的行为。这项服务工作良好约1.5年,但几周后它显示出某种类型的“停电”#34; (不幸的是我无法发布图片,因为我在这里很新。)

虽然仍有来电,但来电/秒降至0。 "中断"总是15秒长。在这15秒之后,处理排队的呼叫。它不能与网络相关,因为90%的呼叫来自同一服务器上的另一个WCF服务,并且没有其他服务(总共10个)受此行为的影响。服务本身确实继续工作,如计算内部资源,进行数据库更新等。不会增加内部工作的执行时间。这种情况发生在18到25分钟左右,但停电时间总是15秒。

OS

Windows Server 2012

WCF作为Windows服务运行

WCF配置:

InstanceContextMode = InstanceContextMode.PerCall,

ConcurrencyMode = ConcurrencyMode.Multiple,

UseSynchronizationContext = false,

IncludeExceptionDetailInFaults = true

Binding = WebHttpBinding

并发节流设置:

MaxConcurrentCalls = 384,

MaxConcurrentInstances = 2784,

MaxConcurrentSessions = 2400

我已经做了一些调查:

  1. WCF油门设置
  2. 我在服务发生的确切时间内完全转储了服务。 ConcurrentCalls和ConcurrentSessions都没用完。转储没有显示可能导致问题的任何异常。

    1. MAX TCP Conenction
    2. 监控活动的TCP连接远非它的限制。

      1. 交换机中的端口中继
      2. 由于没有来电,即使是本地服务(使用localhost),我也很确定它与网络无关。

        1. 加载问题
        2. 低负载(见下文)以及高负载(传入呼叫的​​5倍)会出现此问题。其频率不会根据负载而变化。我还尝试在我的登台系统上重现行为,每秒约600-1000次呼叫。我设法将服务带入一个状态,我发送更多来电/秒,因为服务可以处理。突出的电话增加了,在某些时候,服务当然崩溃了。但这种行为从未出现过。

          1. 线程池耗尽
          2. 当服务运行50个线程并且还有200个线程时,会出现问题。虽然没有更多可用线程,但会出现关于此的错误消息。

            我已经没有可能引起这种行为的事情了。我认为,它可能是GC阻塞线程,因为该服务在RAM中使用大约10GB。它是一种内存缓存服务。或者它可能是操作系统(Windows Server 2012)或与Windows服务本身相关的东西。

            有没有人自己面对这样的事情,或者是否有人知道可能导致这种情况的原因?

            修改:现在我可以发布图片了:

            enter image description here

            编辑: GC堆转储(感谢usr)

            enter image description here

            我看到近50%(总共70%,包括相关参考文献)是由一本大字典引起的。 2700万条目(基于内存转储堆)。我将专注于重构它。里面有很多未使用的物品。也许这会有所帮助。

            此外,我将从msdn添加GC.WaitForFullGCApproach Method,以查看当服务停止处理传入请求时GC是否正在运行。

            当我知道更多时,我会告诉你。

            编辑:GC统计数据(包括停电14秒)

            •CLR Startup Flags: CONCURRENT_GC
            •Total CPU Time: 42.662 msec
            •Total GC CPU Time: 2.748 msec
            •Total Allocs : 1.524,637 MB
            •MSec/MB Alloc : 1,802 msec/MB
            •Total GC Pause: 2.977,2 msec
            •% Time paused for Garbage Collection: 19,4%
            •% CPU Time spent Garbage Collecting: 6,4%
            •Max GC Heap Size: 11.610,333 MB
            •Peak Process Working Set: 14.917,915 MB
            •Peak Virtual Memory Usage: 15.326,974 MB
            

            那"只是"暂停3秒。无论如何,那不应该那么高,我会重构内存存储。但它根本没有解释15秒:(

            编辑:在周末期间,我做了以下事情:

            1. 已安装的最新Windows更新(上次更新时间为2个月前)

            2. 重新启动Windows服务器

            3. 重构了2700万个对象的in-mem存储。我设法将使用的内存从11GB减少到6-8GB(这是相当多的)。那里很旧的代码;)

            4. 到目前为止,问题并没有再次发生(现在大约运行17小时)。这导致我假设GC导致服务暂停或某些操作系统相关问题导致了这种行为。

              我猜这个问题不是解决了#34;在某些时候会重新出现,导致数据会随着时间的推移而增加。

              感谢大家花时间在这上面。我将继续调查转储并尝试详细了解发生的情况。我会告诉你的。

1 个答案:

答案 0 :(得分:0)

如果中断足够可预测,您可以在停电期间连接windbg + SOS并且:

  • 在停电期间暂停服务两次
  • 每次运行!threads~*e!dumpstack以显示线程状态和堆栈

如果你有100个线程在15秒内没有做任何工作,这个应该反映在堆栈中 - 幸运的是你的100个线程的大部分是:

  1. 坚持使用您的一种方法(查看当前帧'每个线程)
  2. 陷入WCF方法
  3. 执行*WaitFor*来电
  4. 执行睡眠/延迟/ IO完成呼叫
相关问题