简体   繁体   English

WCF可靠消息:maxPendingChannels增加后的口吃服务

[英]WCF Reliable Messaging: stuttering service after maxPendingChannels increase

We have an issue whereby during load testing if we fire calls rapidly at one of our services we were getting the error 我们有一个问题,即在负载测试期间,如果我们在我们的某个服务中快速拨打电话,我们就会收到错误

"System.ServiceModel.ServerTooBusyException: The request to create a reliable session has been refused by the RM Destination. Server 'net.tcp://localhost:10511/ParameterMonitorService' is too busy to process this request. Try again later. The channel could not be opened." “System.ServiceModel.ServerTooBusyException:RM Destination拒绝了创建可靠会话的请求。服务器'net.tcp:// localhost:10511 / ParameterMonitorService'太忙,无法处理此请求。请稍后再试。不能打开。”

We increased the value of maxPendingChannels from its default of 4 to 128 and then beyond, and the error has disappeared, now however, rather than throwing the exception the service will just stop processing messages under load and then begin again several minutes later. 我们将maxPendingChannels的值从其默认值4增加到128然后超出,并且错误已经消失,但是现在,不是抛出异常,服务将停止处理负载下的消息,然后在几分钟后再次开始。

It does not seem to drop anything, it just hangs for a while. 它似乎没有掉落任何东西,只是挂了一会儿。 The more we pound the service the longer this recovery seems to take. 我们对服务的攻击越多,这种恢复似乎就越长。

The service is configured as Per-Call with ConcurrencyMode Multiple. 该服务配置为Per-Call with ConcurrencyMode Multiple。 Other behavior settings are: 其他行为设置是:

<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100" maxConcurrentInstances="100"/>

<customBinding>

    <binding name="Services_Custom_Binding" openTimeout="00:00:20" sendTimeout="00:01:00">          
        <reliableSession  ordered="true" inactivityTimeout="00:10:00" maxPendingChannels="128" flowControlEnabled="true" />
        <binaryMessageEncoding>
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />            
        </binaryMessageEncoding>
        <tcpTransport maxPendingConnections="100" listenBacklog="100" />          
      </binding>
  </customBinding>

We are kind of stuck. 我们有点卡住了。 Any help appreciated! 任何帮助赞赏!

This is a classic performance tuning story. 这是一个经典的性能调优故事。 By reconfiguring the throttle on reliable sessions you have removed what used to be the bottleneck in the system, and have moved the bottleneck to somewhere else in your system. 通过在可靠会话上重新配置限制,您已经删除了曾经是系统中的瓶颈,并将瓶颈移到了系统中的其他位置。

You really can't expect people to pluck a diagnosis of where the bottleneck now lies out of thin air, without any details of how your service is hosted, on what hardware, what it is doing, or how it goes about doing it. 你真的不能指望人们在没有任何关于你的服务托管方式,硬件,它在做什么或者如何做到这一点的情况下,毫无疑问地了解瓶颈所在的地方。 You need to instrument your system as comprehensively as you can, using Windows Performance Monitor counters, and interpret these to get an idea of where resource contention is now happening in the system. 您需要使用Windows性能监视器计数器全面检测系统,并解释这些以了解系统中现在发生的资源争用。

My first guess would be that the increased concurrency after removing the session throttle is causing contention for managed thread pool threads, but this is only a guess - really you want to base diagnosis on evidence, not guesswork. 我的第一个猜测是,在删除会话限制后增加的并发性导致了托管线程池线程的争用,但这只是猜测 - 实际上你想要根据证据进行诊断,而不是猜测。

By default the threadpool creates 8 threads and adds only two threads per second thereafter. 默认情况下,线程池创建8个线程,之后每秒仅添加两个线程。 When you fire up a raft of workers at the same time, WCF balks because the threads don't start quickly enough. 当您同时启动大量工作人员时,WCF会因为线程启动速度不够快而无法启动。

This is the solution that works nicely for me, call AdjustThreads whenever you're going to fire up lots of threads: 这个解决方案对我很有用,无论何时你要激活很多线程,都可以调用AdjustThreads:

    Imports NLog
    Public Module AdjustThreads_

    Private _Logger As Logger = LogManager.GetCurrentClassLogger
    Private _MaxWorkers As Integer = 16
    Private _MaxCompletions As Integer = 16
    Public Sub AdjustThreads()
        Dim minworkerthreads As Integer = 0
        Dim maxworkerthreads As Integer = 0
        Dim mincompletionthreads As Integer = 0
        Dim maxcompletionthreads As Integer = 0
        Dim activeworkerthreads As Integer = 0
        Dim activecompletionthreads As Integer = 0
        Threading.ThreadPool.GetMinThreads(minworkerthreads, mincompletionthreads)
        Threading.ThreadPool.GetMaxThreads(maxworkerthreads, maxcompletionthreads)
        Threading.ThreadPool.GetAvailableThreads(activeworkerthreads, activecompletionthreads)
        Dim workers As Integer = maxworkerthreads - activeworkerthreads
        Dim completions As Integer = maxcompletionthreads - activecompletionthreads
        If workers > _MaxWorkers Then
            _MaxWorkers = _MaxWorkers
        End If
        If completions > _MaxCompletions Then
            _MaxCompletions = completions
        End If
        ' If current is (initially) 8, new threads only start twice a second.
        ' So, kick off a minimum of 16 and always increase by 50%
        Dim needworkers As Integer = _MaxWorkers * 3 \ 2
        Dim needcompletions As Integer = _MaxCompletions * 3 \ 2

        If needworkers > minworkerthreads OrElse
           needcompletions > mincompletionthreads Then
            _Logger.Info("Threadpool increasing workers to {0}, completions to {1}",
                         needworkers, needcompletions)
            Threading.ThreadPool.SetMinThreads(needworkers, needcompletions)
        End If
    End Sub
End Module

(damn editor keeps making 'End Module' fall out of the code, if someone could fix it?) (该死的编辑器一直在使“终端模块”脱离代码,如果有人可以解决它?)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM