четверг, 25 мая 2017 г.

[prog] Интересный момент при проектировании round-robin mbox-а.

Работаю над такой штукой для SObjectizer-а как round-robin mbox. Т.е. почтовый ящик, на который могут подписаться N агентов, но доставка сообщений к ним будет осуществляться по очереди, т.е. сперва первому агенту, затем второму, затем третьему и т.д. Эта штука должна быть удобной, например, при реализации балансировки нагрузки, когда требующие обработки сообщения отсылаются в один и тот же mbox, а распределяться они будут при этом на N агентов-воркеров, прозрачным для отправителя образом.

Подобные вещи и раньше можно было делать, но вручную. А теперь есть возможность предоставить round-robin mbox прямо "из коробки".

Однако, в процессе продумывания реализации round-robin mbox-а обнаружилась неожиданная засада. Дело в том, что в mbox-ах есть такая штука, как delivery filters, т.е. фильтры, которые определяют, имеет ли смысл доставлять конкретное сообщение до конкретного получателя.

Например, представим себе, что у нас есть mbox, в который некий агент время от времени отсылает текущие показатели температуры воздуха в комнате. И у нас есть два агента, которые заинтересованы в получении этих сообщений. Один из этих агентов управляет обогревом комнаты и он хочет получать все сообщения (ему нужно понять когда температура снизилась слишком сильно чтобы включить обогрев и нужно понять, когда температура поднялась достаточно высоко, чтобы выключить обогрев). А второй заинтересован только в сообщениях со слишком высокой температурой, дабы инициировать пожарную тревогу. Вот второй агент установит фильтр доставки, в котором будет проверяться значение в сообщении. Если это значение недостаточно высокое, то второму агенту этот экземпляр сообщения доставляться не будет.

Чем же мешают фильтры доставки в round-robin mbox-е?

Как в принципе должен работать round-robin mbox? У него должен быть список подписчиков на каждый тип сообщения. В этом списке должен быть явно отмечен текущий элемент -- тот подписчик, которому должно быть доставлено следующее сообщение. Когда сообщение приходит, оно отсылается этому подписчику, после чего текущим элементом становится следующий подписчик (ну или первый, если мы дошли до конца). Все просто.

Но это мы пока не рассматривали фильтры доставки. В случае с фильтрами доставки мы должны для текущего элемента спросить у его фильтра "А можно ли доставлять сообщение этому подписчику?" Если можно, то все хорошо, работает привычная схема. А вот если фильтр говорит "Нет"? Что делать тогда?

Вырисовываются следующие варианты:

  1. Просто выбросить этот экземпляр сообщения. Т.е. текущему агенту в списке сообщение не доставляется (что естественно, т.к. фильтр запрещает доставку) и не делается попытка доставить сообщение следующему агенту в списке. Текущим становится следующий агент в списке (или первый, если достигли конца списка).
  2. Попытаться выбрать другого получателя. Т.е. сразу перейти к следующему агенту и спросить его фильтр доставки. Потом к следующему и т.д. до тех пор, пока получатель не будет найден. Может быть вообще ничего не найдем, но тогда данный экземпляр сообщения просто выбрасывается.
  3. Тупой запрет на использование фильтров доставки в случае round-robin mbox-а. Тогда проблемы нет в принципе.
  4. Update. Объединить все фильтры доставки в один комбо-фильтр. Когда появляется сообщение, оно сперва пропускается через этот комбо-фильтр (т.е. через все фильтры). И только если комбо-фильтр пропускает сообщение, только тогда оно доставляется текущему получателю.

Лично я пока склоняюсь к первому варианту. Логика такая: round-robin предполагает, что пытаемся доставлять по очереди. Сейчас очередь у агента X. Если X отказывается принимать сообщение, то он все равно свою очередь использовал и для следующего сообщения очередь перейдет к другому получателю.

Вот только не уверен, что это не будет сбивать пользователей с толку. Кто что думает?

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

Кстати, попутно еще один вопрос: а кроме round-robin еще какие-нибудь политики доставки для N агентов кому-нибудь нужны/интересны?

Комментариев нет: