Тайм-аут Polly до вызова execute - PullRequest
0 голосов
/ 20 июня 2019

У меня есть политика, которую я выполняю так:

_logger.LogDebug($"Got the policy for {tenant.TenantCode}");
policy.Execute(
        () =>
        {
            _logger.LogDebug($"Calling _domainEventDLA.GetOldestEvent {tenant.TenantCode}");
            domainEvent = _domainEventDLA.GetOldestEvent(tenant);
            _logger.LogDebug($"Calling _domainEventDLA.GetOldestEvent {tenant.TenantCode}");
        }
    );

У меня установлено тайм-аут на 3 секунды, и я получаю исключение тайм-аута для Polly. Метод в execute занимает менее 100 миллисекунд.

В журнале я вижу первую строку журнала (Получил политику для ...), а следующая записанная запись - это исключение тайм-аута через 3 секунды. Я никогда не вижу строку журнала в execute до фактического вызова метода (Вызов _domainEventDLA ...).

Это политика тайм-аута:

var timeoutPolicy = Policy
                .Timeout(3, timeoutStrategy: TimeoutStrategy.Pessimistic,
                onTimeout: (context, timespan, task) =>
                {
                    _logger.LogError(
                        $"A database timeout occured after {timespan.TotalSeconds} seconds, for tenant {tenant.TenantCode}.");
                });

Это многопоточное приложение, поэтому другие потоки могут использовать ту же политику.

Есть идеи?

1 Ответ

0 голосов
/ 20 июня 2019

Возможно, вы испытываете голодание нити.Проект Polly дает следующее объяснение об использовании политики синхронного пессимистического тайм-аута в случае высокого параллелизма:

Для синхронных выполнений способность вызывающего потока «ходить»«Отойти» от действия, которое в противном случае не может превышать тайм-аут, обходится дорого: чтобы позволить текущему потоку уйти, политика выполняет делегат пользователя как задачу в потоке ThreadPool .

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

Мы рекомендуем пессимистический синхронный TimeoutPolicy в сочетании с явным ограничением параллелизма вызовов в этом кодовом пути.Возможны следующие варианты управления параллелизмом:

  • с использованием Polly BulkheadPolicy (который является дросселем парализма) перед политикой тайм-аута
  • с использованием ограничивающего параллелизм TaskScheduler перед политикой тайм-аута
  • с использованием политики автоматического выключателя перед TimeoutPolicy, с автоматическим выключателем, настроенным на отключение, если слишком много вызовов в нисходящем направлении истекло.Предотвращает чрезмерное количество вызовов, передаваемых в нисходящую систему (и блокирующих потоки), когда она блокирует
  • любые другие встроенные средства управления параллелизмом вызывающей среды.

Похоже, что ваш код испытывает истощение потока: похоже, что при планировании задачи исполняемого делегата поток не доступен из ThreadPool для его выполнения до истечения времени ожидания.

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

...