Ограничение потока событий от триггеров

В версии Оркестратора 1.23.11 добавлена возможность ограничить исходный поток событий от триггеров при его обработке. Настройка помогает устранить либо снизить риск отказа в обслуживании.

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

Параметры ограничения

Чтобы настроить ограничение, внесите изменения в конфигурационный файл WebApi. Нужные параметры содержатся в секции Assignment:

"Assignment": {
    ...
    "ChainLimiterTriggerEventTime": 500,
    "ChainLimiterTriggerEventEmail": true,
    "ChainLimiterTriggerEventSchedule": true,
    "ChainLimiterTriggerEventFromRobot": true,
    "MaxTriggerQueueLength": 10000,
    "MaxLastEventsInterval": 5
  },
  1. ChainLimiterTriggerEventTime - определяет, нужно ли использовать ограничение для потока событий триггеров. Значение задается в миллисекундах, рекомендуется 500. Если указано 0 – ограничение не используется. Также ограничение не используется, если одновременно установлено false для параметров:

    • ChainLimiterTriggerEventEmail;

    • ChainLimiterTriggerEventSchedule;

    • ChainLimiterTriggerEventFromRobot.

  2. ChainLimiterTriggerEventEmail - определяет, нужно ли использовать ограничение для потока событий триггеров почты. Возможные значения: true/false.

  3. ChainLimiterTriggerEventSchedule - определяет, нужно ли использовать ограничение для потока событий триггеров расписаний. Возможные значения: true/false.

  4. ChainLimiterTriggerEventFromRobot - определяет, нужно ли использовать ограничение для потока событий триггеров запуска из роботов. Возможные значения: true/false.

  5. MaxTriggerQueueLength - максимальный размер промежуточной очереди, при превышении которого события будут теряться – фактически означает отказ в обслуживании.

  6. MaxLastEventsInterval - максимальный временной интервал для отображения последних событий уменьшения/увеличения/переполнения внутренней очереди на главной странице. Указывается в минутах.

Как работает ограничение

Рассмотрим подробнее, как работает данное ограничение и как стоит выбирать его параметры.

Пусть на отрезке времени [t0, t9] (рисунок 1, а) на каждом Δt^46 интенсивность потока событий I = Imax. Будем считать интегральной характеристикой потока событий S сумму всех прямоугольников с основанием Δt и высотой I.

Тогда (см. рисунок 1):

  • a) - показывает, что система работает на пределе своих возможностей (Imax, Smax), но с нагрузкой справляется, отказа в обслуживании не происходит.

  • б) - показывает, что на отрезке [t3, t6] будет отказ в обслуживании, так как превышено Imax на этом отрезке, и, как следствие, превышена интегральная характеристика интенсивности потока (так как на остальных Δt I = Imax).

  • в) - показывает, что на отрезке [t3, t6] будет отказ в обслуживании, так как превышено Imax на этом отрезке. Но максимальная интегральная характеристика интенсивности потока не превышена. В этом случае возможно перераспределение нагрузки.

Рисунок 1 - Интегральная характеристика потока событий

Если система принимает и обрабатывает поток событий по простой схеме (рисунок 2, а), то перераспределение нагрузки не используется. Это соответствует значению параметра ChainLimiterTriggerEventTime = 0. Даже без превышения интегральной характеристики интенсивности потока, на пиках система не справится, будет отказ в обслуживании. Контролировать интенсивность для каждого отдельно взятого Δt, которая считается внешним фактором, система принципиально не может.

Рисунок 2 - Схемы распределения нагрузки по принятию и обработке потока событий триггеров

При включенном распределении нагрузки (рисунок 2, б) это соответствует значению параметра ChainLimiterTriggerEventTime > 0, пики нагрузки примет промежуточная очередь. Преобразованный поток событий по своему построению на любом Δt будет иметь I ≤ Imax. Таким образом, очередь сгладит пики, и весь поток будет обработан - но, возможно, с некоторой задержкой.

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

Чтобы оценить интегральную характеристику интенсивности потока, используйте лог событий Оркестратора – таблица OrchEvent.

Одно из трех значений поля Event:

  • AssignmentIncreaseTriggerNativeEventBus = 9016 – внутренняя очередь увеличивается;

  • AssignmentDecreaseTriggerNativeEventBus = 9017 – внутренняя очередь уменьшается;

  • AssignmentOverflowTriggerNativeEventBus = 9018 – внутренняя очередь переполнена.

И поле EntityId для событий увеличения/уменьшения внутренней очереди. Эти события могут быть записаны не чаще, чем с интервалом ChainLimiterTriggerEventTime, так как их наступление проверяется при каждом просыпании потока сбора событий из промежуточной очереди.

Поле EntityId показывает, как меняется процент от MaxTriggerQueueLength использования промежуточной очереди. Используются фиксированные значения: 1 – 25%, 2 – 50%, 3 – 75%.

Событие наступает при переходе вверх/вниз одного из 3-х переходов: 25%, 50%, 75%. Так как промежуточная очередь принимает на себя исходный поток событий, по динамике процента её использования во времени можно оценить интегральную характеристику интенсивности этого потока.

На основе этой оценки можно выбрать приемлемые значения параметров ChainLimiterTriggerEventTime и MaxTriggerQueueLength. А также выработать рекомендации по снижению интенсивности исходного потока событий за счет уменьшения частоты срабатывания триггеров (перенастройка параметров заданий).

Пример оценки интегральной характеристики

Рассмотрим пример оценки интегральной характеристики интенсивности исходного потока на основе лога событий Оркестратора (см. таблицу 1).

Пусть система работает с параметрами ChainLimiterTriggerEventTime=500 и MaxTriggerQueueLength=20. В логе не зафиксировано событие переполнения внутренней очереди – иначе это бы означало отказ в обслуживании, и детальный анализ лога на предмет интенсивности тут уже был не нужен.

Анализ проведем на основе временного окна в 20 сек – выберем события, которые попали в это окно. Пусть это будут 4 события:

SELECT "OrchTimestampUtc",
       	"Event", 
"EntityId" 
FROM "OrchEvents"
WHERE "Event" in (9016, 9017, 9018) 
  	AND "OrchTimestampUtc" BETWEEN '2023-11-10 11:00:00' AND '2023-11-10 12:00:00'
	AND "NodeId"  = 0
ORDER BY "OrchTimestampUtc" ASC;

Таблица 1 – Лог событий увеличения/уменьшения процента использования внутренней очереди событий от триггеров

Так как Δt = ChainLimiterTriggerEventTime = 500, тогда таблица 1 преобразуется в таблицу 2. Нумерация строк в таблице 2 начинается с нуля.

Таблица 2 – Интенсивность исходного потока событий от триггеров

Очередь разбирается с интенсивностью 1 сообщение в 500 мсек. За одно обращение из очереди читается не более одного элемента. В таблице 2 видно, что:

  • После первого роста очереди на 25% (№ 0–7), что значит от 5-ти до 10-ти элементов в очереди, до следующего уменьшения из очереди читается 8 элементов. Поскольку событие уменьшения очереди зафиксировано после чтения 8-ми элементов, значит очередь в этот промежуток принимала события.

  • После первого уменьшения очереди на 25% (№ 8–11), что значит менее 5-ти элементов в очереди, до следующего роста из очереди читается 4 элемента. Те элементы, которые были в очереди на момент фиксации её уменьшения на этом промежутке вычитаны полностью. Но сразу следом идет увеличение очереди - это говорит о том, что очередь в этот промежуток опять принимала события.

  • После второго роста очереди на 25% (№ 12–19), что значит более 5-ти элементов в очереди, до следующего уменьшения из очереди читается 8 элементов. Так как событие уменьшения очереди зафиксировано после чтения 8-ми элементов, значит очередь и в этот промежуток принимала события.

  • После второго уменьшения очереди на 25% (№ 20) таблица заканчивается, но очередь в этот момент не пустая.

Таким образом, имеем два 25%-ных пика интенсивности, которые приняла на себя очередь.

В целом интенсивность исходного потока не является для системы критической, но обработка событий идет с небольшой задержкой: примерно в 5 элементов. В данном случае, если у системы есть запас мощности, можно уменьшить ChainLimiterTriggerEventTime, и тогда:

  • события будут извлекаться на обработку чаще;

  • внутренняя очередь будет расти медленнее, возможно, её рост даже не будет зафиксирован в логе.

Увеличивать MaxTriggerQueueLength не имеет смысла, так как пики невысокие – 25%.

Last updated