актор 0.*

gattsu

Выдающийся
Проверенный
Победитель в номинации 2018
Победитель в номинации 2017
За веру и верность форуму
За заслуги перед форумом
Преподаватель
Сообщения
165
Розыгрыши
0
Репутация
1 457
Реакции
293
Баллы
1 393
более менее оптимальный вариант, проектирование систем на основе акторов, в java.
Для простоты и прозрачности, логики, все поведение програмируется внутренними классами.
Реализовал базовый набор по Hewitt-у, во время обработки сообщения, актор может:
- отправлять сообщения другим акторам и самому себе(рекурсивное сообщение) (метод Context.send и Reference.send)
- менять свое поведения (метод Context.become)
- создавать других акторов (метод Context.create)

О поведении актора, на основе просто примере будет более наглядно:
Код:
package fact.samples;

import fact.Context;

public class Account implements Context {
    final String login;
   
    final String password;
   
    Account(String login, String password) {
        this.login = login;
        this.password = password;
    }
   
    public void define() {
        become("Free");
    }
   
    public void logout() {
        System.out.println("wrong logout");
    }
   
    public class Free {
       
        public void login(String login, String password) {
            if(Account.this.login.equals(login) && Account.this.password.equals(password)) {
                System.out.println("login success");
                become("Login");
            } else
                System.out.println("wrong login or password");
        }
       
    }
   
    public class Login {
       
        public void login(String login, String password) {
            System.out.println("account in use");
        }
       
        public void logout() {
            System.out.println("logout");
            become("Free");
        }
    }
}
В данном коде, есть актор Account, у которого, есть два поведения(внутренних класса) Free и Login. У каждого из них есть, свои обработчики сообщений.
Если расширить данный пример, можно реализовать актор для сервера авторизации.
Замечание: если пришло сообщение, которого нету в заданном поведение, то метод для обработки сообщения ищеться в базов классе. В данном примере, если отправить сообщение logout, когда актор установлен как Free, будет вызван обработчик из базового класса Account, на экран консоли, выведиться сообщение "wrong logout"

Пример использования:
Код:
package fact.samples;

import fact.Context;
import fact.Model;
import fact.Reference;

public class AccountSample implements Context {

    public void define() {
        Reference account = create("account", new Account("root", "root"));
        account.send("logout");
        account.send("login", "root", "1243");
        account.send("login", "root", "root");
        account.send("login", "root", "root");
        account.send("logout");
        account.send("logout");
        account.send("login", "root", "root");
    }
   
    public static void main(String...args) {
        Model.launch(new AccountSample());
    }
   
}
console output:
Код:
wrong logout
wrong login or password
login success
account in use
logout
wrong logout
login success
 

- Добавил отправку сообщений с задержкой
Код:
package fact.samples;
import fact.Context;
import fact.Model;
public class CounterDelay implements Context {
    private long count = 0;
   
    public void define() {
        send("print").delay(1000);
        send("tick");
    }
   
    public void tick() {
        count++;
        send("tick");
    }
   
    public void print() {
        System.out.println(count);
        count = 0;
        send("print").delay(1000);
    }
   
    public static void main(String...args) {
        Model.launch(new CounterDelay());
    }
}

В данном примере, актор отправляет себе два сообщение:
- print с задержкой 1сек
- tick без задержок
оба сообщения рекурсивны. На каждое сообщения tick, увеличивается счетчик, на каждое сообщения print отображается показатель счетчика и затем сбрасывается на ноль.

Заложил сетевой фреймворм, на основе
Для простого примера реализавал, ехо сервер.
 
Обновил. "немного" переделал код. Интерфейс остался обратно совместимый. Исключение запросы.
- добавил полный цикл обслуживания актора create/stop/resume/terminate(kill).
При остановке, возврате или удаленния актора, можно устанавливать,обратный вызов, функция которая будет вызвана, в случае успешной операции.

Примечани: Функции обратного вызова должны быть определенны в классе актора.
 
Управление запросами
Для запрос к другому актору, нужно объявить класс-поведение, и задать методы с возможной сигнатурой ответа. При вызове метода request, возвращается объект Future, в котором черем метод handle, нужно указать имя поведения, для обработки ответа.
Внимание: если не указать поведение, то запрсов не выполниться.
При ответе, актор может получить сообщения типа reply или complaint, в классе-поведения обрабатывающий запрос, нужно покрыть возможные варианты сигнатуры сообщения.

Пример:
Есть актор Account, в котором присутсвует медот-обработчик login. При обработке сообщения, если данные логина и пароля, соответсвует данным аккаунта, то Account отправляет объект LoginSuccess, если не правильные данные, то отвечает через метод complaint, отправляет LoginFail.WrongLoginOrPassword.
Код:
package fact.samples;

import fact.Context;

public class AccountRequest implements Context {
    private String login;
   
    private String password;
   
    public AccountRequest(String login, String password) {
        this.login = login;
        this.password = password;
    }
   
    public void login(String login, String password) {
        if(this.login.equals(login) && this.password.equals(password)) {
            reply(success);
        } else
            complaint(LoginFail.WrongLoginOrPassword);
    }
   
    public static class LoginSuccess {
        private LoginSuccess() { }
    }
   
    private final static LoginSuccess success = new LoginSuccess();
   
    public enum LoginFail {
        WrongLoginOrPassword,
        AccountInUse
    }
}

В акторе который производит запрос, присутсвует класс поведения Request, в котором определенны два обработчика, на успешный запрос и провальный запрос. Для простоты, создаем актор-аккаунт, на месте.


В примере показывается, что вовремя запроса, актор будет обрабатывать, только ответ. Другие сообщения обрабатываются после запроса, то есть актор блогируется для обработки входящих сообщения, за исключение ответа на запрос.
Код:
public class RequestSample implements Context {
    Reference account;
   
    public void define() {
        account = create("account", new AccountRequest("root", "root"));
        account.request("login", "login", "login").handle("Request");
        send("tick");
        send("print");
    }
   
    public void tick() {
        account.request("login", "root", "root").handle("Request");
        send("print");
    }
   
    public void print() {
        System.out.println("print");
    }
   
    public class Request {
       
        public void reply(LoginFail fail) {
            System.out.println("login failed");
        }
       
        public void reply(LoginSuccess success) {
            System.out.println("login success");
        }
    }
   
    public static void main(String...args) {
        Model.launch(new RequestSample());
    }
}

История вычислений данного примера:
0 E AccountRequest <~~ [request: login("login", "login"), to: RequestSample ]
1 E RequestSample <~~ [complaint: LoginFail.WrongLoginOrPassword]
console "login failed"
2 E RequestSample <~~ [tick()]
3 E AccountRequest <~~ [request: login("root", "root"), to: RequestSample ]
4 E RequestSample <~~ [reply: LoginSuccess]
console "login success"
5 E RequestSample <~~ [print()]
console "print"
6 E RequestSample <~~ [print()]
console "print"
 
  • Мне нравится
Реакции: kick
- Переделал сетвой API. Реализовал пример эхо сервера.( Соединение отправляет каждые 100 мс строку, сервер читает её отображает на консоль и отправляет обратно, клиент читае и отображает на консоль)
- Переместил сетевой API в репозиторий ядра.
- Добавил методы для определения типа сообщения(запрос, ответ, ответ-ошибка)
 
  • Мне нравится
Реакции: kick
Обновил:
- реализовал цепочку запросов
- реализовал передачу запрос(continuation)
- реализовал управляющие методы статическим путем, объявленны в fact.ActorContext. Теперь можно получить доступ к управляющим метода чере import static

Добавил соответствующие примеры
 
  • Мне нравится
Реакции: kick
Исправиль некоторые ошибки.
Немного . Написал каркас для сервера авторизации.(interlude)
Нужно организовать
- работу с базой данных
- работу с игровыми серверами. Написать, proxy для игрового сервера.
- переписать сетевую библиотеку, организовать чтение по требованию.

ПС: Для меня не понятно, каким образом работает реализация, криптографии, добавление контрольной суммы и шифровка первого пакет xor ключем. Отсутвует
смешение, для задания предела, самое интересное, если подать буффер в котором, уже записанно, минимум 4 байта, то криптография накроется медным тазом. У меня закрались дикие сомнения, что реализация на l2j, если её топорным путем перенести на С не будет работать, так как в jvm зануляет все значения в созданных массивах. Понятно, что в сервере авторизаии, может быть только один пакен на запись и один на чтение, по протоколу, но это всеравно не делает менее ужасней эту криптографию.
Не могу понять почему выдает ошибку контрольной суммы, переодически... магия...

ПС Двойная авторизация, в l2j вообще кабздец, как так можно было сделать. Ошибка, котороя тянется на все сборки
 
Оффтоп:
Тема одного актёра?
 
  • Мне нравится
Реакции: kick
Человек описывает свою работу, не нравится внесите свою лепту
да не, мне всё нравится) Просто как-то без поддержки сторонних участников и советов других мастеров. Ощущение что человек сам с собой тут общается.
 
у меня закралось чувство, что никто, в этой теме отписавшийся, не шарит в теме:) а все заинтересованные в процессе изучения и творческих мыслях :)
 
Оффтоп:
Вообще ничего не понял :D
Умный дядька видать)
 
Последнее редактирование:
  • Мне нравится
Реакции: 6yka




ПС Пару программок c использование akka и оно вставит

Оно просто не на той стадии, на которой может пользу принести. Мне надо написать для отладки библиоткеу, покрыть все тестами, мануалы сделать и тогда можно будет, что-то понять, а так только для тех кто в теме. Вот когда сделаю кластерную систему, горячую замену кода актора, тогда будет весело. По сути можно будет обновить код сервера не перезагружая его.
 
  • Мне нравится
Реакции: Psycho и 6yka

    6yka

    Баллов: 42
    разжевал, теперь то всё понятно =)
просто непонятные каракули
 
Оффтоп:
Он с другой планеты, отвечаю! :Omgnooo:
 
  • Мне нравится
Реакции: 6yka
Немного рассуждений.
Все в реализации мучает, несколлько проблем.
Первая проблема. Проблема точки входа, как не крути точку входа приходится реализовывать костылями. Суть проблемы, в том, что вычисление в модели происходит путем обмена сообщениями и их обрботки, у каждого сообщения, есть активурующее, то сообщения, в момент обработки, было сгенерированно, а первое сообщения в системе не имеет активурующего. Это как проблема физики, модели акторов получила вдохновения от туда и проблемы, зарождение вселенной. Была ли вселенная самого начала, был ли большой взрыв? Это же все точка входа, для вселенной... Все физики, ищут точку входа для вселенной.

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

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

Так же можно и в la2, вам не интересен человек на другом конце карты, так как вы взаимодействуете с ближайшим окружением.
 
Добавил sbt сборку
Прикрепил текущий билд

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

Участники форума, могут предлагать различные примеры прогамм, а я их реализую в рамках модели актора, с помощью библиотеки.
 
Последнее редактирование:
Спасибо за ваш труд
 
Назад
Сверху Снизу