Pull to refresh

Comments 6

В подобных очередях, в нашей системе, помимо ограничения размера очереди, при достижении которого сообщения начинают теряться, мы устанавливаем лимит для срабатываний предупреждений, при достижении которого идет запись в лог или уведомляется система мониторинга. Лимит для предупреждений выбираем на порядок или два меньше ограничения размера очереди, но он должен срабатывать относительно редко. Например ограничение очереди 100000 элементов, а предупреждения уже начинают идти при ее разрастании более 1000. Лимит на размер очереди выбирается так, чтобы при полном ее заполнении система смогла бы ее «разгрести» за разумное время при возвращении системы в рабочий режим.
Это как раз то, о чем речь шла в статье: хороший механизм overload control затачивается под определенные условия. Тут пространство для вариантов весьма большое. Например, можно настроить несколько уведомлений для очереди: когда ее объем превышает 1000, 10000 и 100000 экземпляров. Причем уведомления могут быть как о превышении (т.е. когда объем превышает 10000), так и о падении ниже порога (т.е. когда объем опускается ниже 1000). Можно много чего придумать.

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

Универсального нет, но есть такой, который может подойти большинству и на мой взгляд должен использоваться по умолчанию: backpressure. Т.е. это когда сущность, которая перегружает другую сущность, останавливается и не выполняет работу до тех пор, пока очередь не разгребется до определенного значения.


В связи с этим вопрос: есть ли такая возможность у SObjectizer?

Обычный send в SObjectizer асинхронный — он не блокируется. Сделано это для того, чтобы не заблокировать самого себя, если и получатель, и отправитель работают на одном и том же рабочем контексте. Это запросто возможно, т.к. агенты могут быть привязаны к одному и тому же диспетчеру.

Приостанавливает отправителя синхронный запрос (т.е. request_value вместо send). Но он приостанавливает в любом случае. Даже если нагрузка на получателя находится в разумных пределах.

А вот если send выполняется для message chain с ограничением на размер, то send может быть приостановлен на некоторый тайм-аут. Если в течении этого времени места для сообщения не нашлось, то SO-5 предпринимает одно из следующих действий: бросает исключение (т.е. игнорирует новое сообщение, но с большим треском), тихо выбрасывает новое сообщение, тихо выбрасывает самое старое сообщение или же вызывает std::abort. Так что на message chain можно делать backpressure, но здесь будут свои сложности. В том числе и в случае, когда отправитель и получатель работают на одном и том же контексте.
Есть ли в SObjectizer способ заменять сообщения в очереди?
Т.е. отправили запрос на ресайз картинки, потом второй запрос на ресайз этой же картинки.
Если обработчик еще не приступил к выполнению первого запроса, то можно исключить его из очереди, т.к. его результат уже не нужен.
Нет, в штатных очередях такой возможности нет.
В этом случае отлично работает схема collector-performer. Collector сначала складирует запросы у себе. Поскольку он знает структуру запроса, он знает, по какому критерию проверять сообщения на уникальность (т.е. что в сообщении является уникальным ключом). Плюс, Collector может использовать структуры данных, которые поддерживают возможность удаления элементов по ключу (например, это может быть Boost.Multindex, первым ключом может быть имя картинки, вторым ключом — порядковый номер).

Мы несколько раз использовали такую схему. И одной из задач Collector-а была как раз отбрасывание запросов-дубликатов.
Sign up to leave a comment.

Articles