вторник, 2 июня 2015 г.

[prog.sobjectizer] Ответ на вопрос о "голодании агентов"

На LOR-е задали очень хороший вопрос:

...скажите пожалуйста как решается проблема с thread starvation если например какие-то актеры выполняют cpu intensive или blocking IO задачи, а каким-то другим актерам нужна высокая отзывчивость?

Написал развернутый ответ там же. Но, т.к. вопрос очень хороший, то имеет смысл продублировать ответ и здесь:

Эти вопросы решаются за счет создания такого количества диспетчеров, которое нужно приложению.

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

Сейчас «из коробки» есть такие диспетчеры:

  • one_thread, все привязанные к диспетчеру агенты работают на одной общей нити;
  • active_obj, каждый агент получает свою собственную рабочую нить;
  • active_group, каждой отдельной группе агентов выделяется своя рабочая нить;
  • thread_pool, привязанные к диспетчеру агенты распределяются между нитями из пула;
  • adv_thread_pool, так же пул нитей на которых работают агенты, но если агент декларирует свои события как thread-safe, то несколько событий одного агента могут обрабатываться параллельно на соседних нитях пула.

За счет этого можно сделать, например, так:

  • выделить one_thread-диспетчер для агента, который будет работать с MQ-шным сервером по AMQP (т.е. подписываться/читать/публиковать);
  • выделить thread_pool-диспетчер для агентов, которые выполняют прикладную обработку полученных от MQ сообщений;
  • выделить active_obj-диспетчер для агентов, которые будут выполнять операции с СУБД;
  • выделить active_obj-диспетчер для агентов, который будут работать с подключенными к компьютеру устройствами (вроде HSM, SmartCard-ридерами, I/O-контроллерами и т.д.)

При этом программирование в агентах на SO5 не похоже на таковое в Erlang или CAF. Оно скорее напоминает SEDA-подход со стадийностью обработки прикладных задач. В SO5 под каждую стадию (I/O, DBMS, ext.device, etc) выделяется агент/группа агентов со своим диспетчером и своим рабочим контекстом. Агенты, которые занимаются только быстротечным диспатчингом запросов (т.е. получили сообщение, проанализировали куда оно идет, переслали, получили ответ, проанализировали, отправили дальше), собираются либо на единичных one_thread диспетчерах, либо в виде групп на active_group-диспетчерах, либо на одном-двух (adv_)thread_pool диспетчерах.

При этом важно отметить еще и то, что агенты и типы диспетчеров — это ортогональные друг другу понятия. Один и тот же агент, в зависимости от задачи, может быть привязан как к one_thread, так и к adv_thread_pool диспетчеру. В коде самого агента от этого ничего не изменится. Что так же сильно упрощает разработку софта с использованием SO5.

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