![]() |
Долго мучаюсь, но вот уже созреваю до конечной программной концепции, своей реализации модели акторов.
Для общего ознакомления рекомендую почитать статью на википедиии Модель акторов — Википедия Для полного ознакомления, рекомендую почитать: Цитата:
- в системе есть фиксированное количество потоков(worker). - отсутствует блокирующая синхронизация - синхронизация с помощью atomic(в класе EventBus) - распределение вычислений делайте actorsystem(global Пытаюсь сделать полностью однородную среду, реализовать по принципу "все есть актор". Сейчас переписываю в 100 раз. Пытаюсь замкнуть все контексте и производить обработку пулом, но при этом оставить однородность. Если будут вопросы пишите, пока не могу расписать, что да как, но думаю на конкретные вопросы смогу ответить. Думаю уже близко к концу, удовлетворяющему меня варианту. actor-model / actors — Bitbucket ПС пакет actor.test содержит пару примеров реализации. Да, про другие реализации модели акторов, автор знает и пробовал на них делать программы. Немного абстрактного кода для примера из ла2 Цитата:
|
Обновления:
Создал новую ветку. Пробую реализовать, другим способом: - уменьшилось количество этапов передачи сообщения(Сообщение передается на прямую без посредником, посредник только при отправке сообщения через не связанную ссылку) - удалось увеличить количество обрабатывающих сообщений на 70-80%. (для разного рода действий, следует организовывать разную балансировку между акторами, можно попробовать реализовать рекомендацию, для балансировщика, при создании актора, по принципу привязки к одному воркеру и тп) - Атомарная синхронизация в каждом mailbox - через класс Balancer, происходит передача, Worker-ам, на исполнение событий. ПС В один момент времени класс актор, может обрабатывать только одно входящее сообщение |
Расширил функционал очереди. Добавил различные функции, которые учитывают указанную задержку, для обработки.
Пробую алгоритм рекурсивных сообщений, в различных случаях позволяет добиться 15-20 миллионов сообщений в секунда, на 3000 акторов.(тест на счетчиках) Система с единичным акторов позволяет достичь 5 миллионов сообщений(единичный счетчик) Тест конечно частного случая, но позволяют следить за пропускной способность, задержкой. Если добавить нагрузку в обработку сообщений, можно получить меньший результат. Уменьшил количество мест синхронизаций, до двух, на одну обработку события. Потоки могут войти в монитор, при обращении к одному и тому же актору(публикация события) Потоки могут войти в монитор, если при балансировке, указал один и тот же поток порождения задачи, для двух других. Прикрепил общую схему работы воркеров(потоков) |
Продолжим.
Реализовал систему с помощью обычной синхронизации, не блокирующие очереди оставил на потом. Реализовано все топорно, чтобы работал фундамент. На данный момент можно: - создавать актор - отправлять сообщение актору - делать запрос с ожиданием ответа к актору. Основные принципы акторов. Каждый актор в один момент времени, может обрабатывать только одно входящее сообщение. Во время обработки сообщения актор может: - менять свое поведения, для реакции на следующее сообщение. - посылать сообщения другим акторам, включая себя(рекурсивное сообщение) - создавать других акторов |
"Один актор не является актором. Актор является частью системы акторов"
Рассмотри простой пример двух акторов. У нас, есть два актора Ping и Pong. Акторы, с задержкой в одну секунду, пересылаю друг другу сообщения. Актор Ping отправляет строку "ping" актору Pong. Получив строку, Pong отображает её и отправляет строку "pong". Получив сообщение актор отображает строку и отправляет сообщение "ping". Этот процесс происходит до выхода из программы, пользователем. Точка входа в модель Код: Код:
public static void main(String...args) {Производим создание актора Pong Код: Код:
system.create(Pong.class, "pong")Первый аргумент типа Сlass, передается класс который наследует BaseActor, в нашем случае Pong.class Второй аргумент типа String - уникальное имя актора в узле. "pong" Производим создание актора Ping Код: Код:
system.create(Ping.class, "ping", system.create(Pong.class, "pong"))Первые два аргумента являются идентичными, а в третий передается массив аргументов(синтаксический сахар vargs, Object...arss эквивалентно записи Object[] args). Система произведет поиск соответствующего конструктора, с заданными аргументами. В нашем случае будет вызван конструктор, для класса Ping Код: Код:
public Ping(Actor actor) {Другой вариант записи Код: Код:
public static void main(String...args) {consumer - функция поведения для указанного типа, она вызывается в случае, когда актор получает соответсвующий тип сообщения type - класс типа T - тип значения Код: Код:
IBehavior behavior = behavior();В нашем примере поведение двух акторов выглядим следующим образом Дла актора Pong Код: Код:
public static class Pong extends BaseActor {То есть, получении сообщения типа String, мы отображаем его в консоли, затем отправляем сообщению "ping", отправителю, с задержкой в одну секунду. Для актора Ping Код: Код:
public static class Ping extends BaseActor {Код: Код:
behavior().Данное сообщение актор получает, обрабатывает, в первую очередь, затем все осталньные входящие, если на момент создания такие есть. В шаблонном поведении Define, мы отправляем сообщение актору pong, который передали при создании, pong.send("ping"). Это является источником вычислений в данной модели. То есть при создании актора ping мы отправляем сообщение актору pong, на что, в случае актора pong, он получает и обрабатывает сообщение, отобразив его на консоли и ответив сообщением "pong". Результат выполнения данной программы будет, бесконечное, поочередное отображения, на консоли, строк "ping" и "pong" Цитата:
ПС На данный момент, в этой имплементации, не реализована отправка сообщения по адресу. |
Расширил управление поведением. Добавил:
- возможность предиката (actor.samples.EvenAndOdd) - возможность задавать поведения, для определенных значения(actor.samples.ValuesCase) Добавил подержу синглтон акторов. Синглтон актор - актор, объект которого может находиться в одном экземпляре, в системе. Singletonрасширяется BaseActorкласс. Объявление синглтон актора, делается путем наследования класса Singleton. Любой актор расширяемый от класс Singleton, сможет быть создан, в одном экземпляре, в системе, через метод create. Обращение, к синглтон актору, можно сделать путем вызова метода actor(T.class), определенного в классе BaseActor. T класс должен быть расширяем actor.Singleton. Вызов данного метода возвращает ссылку на заданный актор. Примечание: actor(T.class) может вернуть ссылку на не существующий синглтон. Пример реализации PingPong через singleton |
Обновление.
- Добавил актор-консоль. Через трейт actor.util.Consol.TConsole, добавляется метод, через который можно отправлять строку на консоль(println(Object)). - Добавил систему остановки акторов. При вызове метода stop, для актора, генерируется событие Event.Stop. При обработке его, актор получает сообщение Actor.Stop, которое можно обработать, производя действия с останавливающим акторов. При остановке, актор удаляется из системы. - Теперь ссылку на корневой актор можно получить через метод system, определенный в классе ActorBase. - Для корневого актора добавлена возможность отображения дерева акторов. Через строковое сообщение "dump-tree". Пример можно посмотреть (src/test/java/actor.test.DumpTreeTest) - Добавил поиск актора по адресу. - Добавил возможность общения запрос-ответ. |
behavior -> case - напомнило Pattern matching из скалы)
|
Ну она где-то так и есть. D java нету механизма pattern matching. Но в данном случае получается reactive парадигма. Программируемое поведение на лету.
В scala бы этот участок был бы грациозней хД |
Всё? Конец?
|
| Время: 12:38 |