Надежные сообщения WCF: служба заикания после увеличения maxPendingChannels - PullRequest
3 голосов
/ 22 февраля 2011

У нас есть проблема, из-за которой во время нагрузочного тестирования, если мы быстро выполняем вызовы в одном из наших сервисов, мы получаем ошибку

"System.ServiceModel.ServerTooBusyException: запрос на создание надежного сеанса был отклоненМесто назначения RM. Сервер 'net.tcp: // localhost: 10511 / ParameterMonitorService' слишком занят, чтобы обработать этот запрос. Повторите попытку позже. Не удалось открыть канал. "

Мы увеличили значение maxPendingChannelsот значения по умолчанию от 4 до 128, а затем и далее, и ошибка исчезла, однако теперь, вместо того, чтобы выдавать исключение, служба просто прекратит обработку сообщений под нагрузкой, а затем возобновит работу через несколько минут.

Это делаеткажется, ничего не роняет, просто висит на некоторое время.Чем больше мы тратим службу, тем дольше длится это восстановление.

Служба настроена как Per-Call с ConcurrencyMode Multiple.Другие настройки поведения:

<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>

Мы застряли.Любая помощь приветствуется!

Ответы [ 2 ]

2 голосов
/ 22 февраля 2011

Это классическая история настройки производительности.Переконфигурировав дроссель на надежных сеансах, вы удалили то, что раньше было узким местом в системе, и переместили это узкое место в другое место в вашей системе.

Вы действительно не можете ожидать, что люди будут ставить диагноз того, где узкое место теперь находится на пустом месте, без каких-либо подробностей о том, как работает ваш сервис, на каком оборудовании, чем он занимается или какделает этоВам необходимо как можно более полно настроить систему, используя счетчики системного монитора Windows, и интерпретировать их, чтобы получить представление о том, где сейчас происходит конфликт ресурсов в системе.

Мое первое предположение состоит в том, что увеличениеПараллелизм после удаления дросселя сеанса вызывает конфликты для потоков пула управляемых потоков, но это только предположение - на самом деле вы хотите основывать диагностику на доказательствах, а не на догадках.

0 голосов
/ 08 мая 2018

По умолчанию пул потоков создает 8 потоков и добавляет только два потока в секунду после этого.Когда вы одновременно запускаете кучу рабочих, WCF блокируется, потому что потоки запускаются недостаточно быстро.

Это решение, которое хорошо работает для меня, вызывайте 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

Конечный модуль

(чертов редактор все время заставляет 'Конечный модуль' выпадать из кода, если кто-то может это исправить?)

...