Хотелось бы понять, как в схемах с применением модели Акторов решаются следующие вопросы. Подскажите, пожалуйста:
1) Как выбирается, какому Актору отправляется сообщение? Видимо, должен быть один общий объект, который хранит список ссылок на эти Акторы? А иначе, как определить, куда нужно слать сообщение?
2) Из первого вопроса, возникает второй. Может ли один Актор хранить список из нескольких других Акторов, или это архитектурно неверно?
3) Каждый Аксторов в модели Акторов имеет свою изолированную память. Тогда каким образом решается вопрос передачи объектов между Акторами? Например, Актор содержит в себе список объектов. Нужно один из этих объектов передать другому Актору.
13.02.12 09:06: Перенесено модератором из '.NET' — TK
Хотелось бы еще добавить, что вопросы эти возникли потому, что я, как мне кажется не совсем правильно использую библиотеку Retlang, чтобы реализовать модель Акторов. Например, вместо того, чтобы публиковать сообщение в канал, я просто ставлю делегат в очередь фибера. Сейчас приходит понимание того, что Актор, это по сути комбинация Фибера и Канала, на который данный Фибер подписан, чтобы реагировать на входящие сообщения. Хотя, возможно, что и это неверно...
E>1) Как выбирается, какому Актору отправляется сообщение? Видимо, должен быть один общий объект, который хранит список ссылок на эти Акторы? А иначе, как определить, куда нужно слать сообщение?
Сообщение отправляется в Event Bus. Акторы, заинтересованные в каком-то типе сообщений подписываются на них каким-либо способом — зависит от реализации. Напрямую связывать акторы не рекомендуется — сразу теряется один из основных бонусов архитектуры, независимость частей программы друг от друга.
E>2) Из первого вопроса, возникает второй. Может ли один Актор хранить список из нескольких других Акторов, или это архитектурно неверно?
Можно все что угодно, но чем меньше акторы знаю друг о друге, тем лучше. В идеале акторы броадкастят сообщения "всем заинтересованным" и подписываются на интересующие их сообщения. Это хорошо поддается юнит тестам.
E>3) Каждый Аксторов в модели Акторов имеет свою изолированную память. Тогда каким образом решается вопрос передачи объектов между Акторами? Например, Актор содержит в себе список объектов. Нужно один из этих объектов передать другому Актору.
Если язык программирования поддерживает ссылки на объекты с подсчетом числа ссылок — то передаешь список объектов целиком, это не тратит ресурсов. Если есть что-то специфичное, вида "общая база данных в миллиард записей, которая постоянно обновляется" — то это рекомендуется вынести из архитектуры акторов и использовать специфические инструменты, в зависмости от ситуации — синглтон доступа там, процедурное API или что еще.
Если язык программирования не поддерживает ссылки на объекты с подсчетом ссылок... То у нас проблемы .
Здравствуйте, Eldar9x, Вы писали:
E>Хотелось бы понять, как в схемах с применением модели Акторов решаются следующие вопросы. Подскажите, пожалуйста:
E>1) Как выбирается, какому Актору отправляется сообщение? Видимо, должен быть один общий объект, который хранит список ссылок на эти Акторы? А иначе, как определить, куда нужно слать сообщение?
В зависимости от реализации, конечно, но у актора может быть адрес (или mailbox), зная который, можно отправлять ему сообщения.
E>2) Из первого вопроса, возникает второй. Может ли один Актор хранить список из нескольких других Акторов, или это архитектурно неверно?
Актор может создавать других акторов, и при этом он может помнить их адреса.
E>3) Каждый Аксторов в модели Акторов имеет свою изолированную память. Тогда каким образом решается вопрос передачи объектов между Акторами? Например, Актор содержит в себе список объектов. Нужно один из этих объектов передать другому Актору.
Через механизм сообщений. В сообщении вы передаёт ссылку на объект, при получении сообщения другой актор может с ним работать.
Спасибо всем за ответ!
E>>1) Как выбирается, какому Актору отправляется сообщение? Видимо, должен быть один общий объект, который хранит список ссылок на эти Акторы? А иначе, как определить, куда нужно слать сообщение?
EOH>Сообщение отправляется в Event Bus. Акторы, заинтересованные в каком-то типе сообщений подписываются на них каким-либо способом — зависит от реализации. Напрямую связывать акторы не рекомендуется — сразу теряется один из основных бонусов архитектуры, независимость частей программы друг от друга.
Получается, что должен быть один общий канал сообщений, в который каждый Актор публикует свои сообщения. То есть любое сообщение должно быть опубликовано в этот канал и все существующие в приложении в данный момент времени Акторы получат его. Но будет ли оно обработано, зависит уже от конкретного Актора. Правильно понимаю?
Тогда получается, что Актор, отправляя сообщение, не знает, кому он его отправляет? Но ведь это противоречит вот этому:
Другой важной характеристикой модели акторов является локальность. Локальность означает, что при обработке сообщения актор может отправлять сообщения только по тем адресам, которые он получил из этого сообщения, по адресам, которые он уже имел до получения сообщения, и по адресам, которые он создал при обработке сообщения.
Другими словами, Актор должен знать, кому он отправляет сообщение. Сейчас у меня сделано так: Есть интерфейсы Актора IAgent, простого сообщения IMessagе, запроса и ответа IRequest и IReply. Последние три — вообще не имеют методов, и используются как параметры для методов IAgent. Снаружи используется только IAgent и обращаться к объекту-Актору мы можем только через этот интерфейс. Акторы реализуют два метода простой отправки и запроса с ожиданием ответа (с таймаутом). Таким образом, мы можем отправлять любые сообщения, запрашивать любые данные, главное, чтобы объекты сообщения, запроса и ответа были immutable и реализовывали соответствующие интерфейсы. Обработает ли Актор сообщение или ответит ли на запрос, зависит от конкретного Актора. Каждый Актор регистрирует соответствующий тип сообщений, запросов и ответов и их обработчики. Вот так правильно сделано?
E>>2) Из первого вопроса, возникает второй. Может ли один Актор хранить список из нескольких других Акторов, или это архитектурно неверно?
EOH>Можно все что угодно, но чем меньше акторы знаю друг о друге, тем лучше. В идеале акторы броадкастят сообщения "всем заинтересованным" и подписываются на интересующие их сообщения. Это хорошо поддается юнит тестам.
E>>3) Каждый Аксторов в модели Акторов имеет свою изолированную память. Тогда каким образом решается вопрос передачи объектов между Акторами? Например, Актор содержит в себе список объектов. Нужно один из этих объектов передать другому Актору.
EOH>Если язык программирования поддерживает ссылки на объекты с подсчетом числа ссылок — то передаешь список объектов целиком, это не тратит ресурсов. Если есть что-то специфичное, вида "общая база данных в миллиард записей, которая постоянно обновляется" — то это рекомендуется вынести из архитектуры акторов и использовать специфические инструменты, в зависмости от ситуации — синглтон доступа там, процедурное API или что еще.
EOH>Если язык программирования не поддерживает ссылки на объекты с подсчетом ссылок... То у нас проблемы .
Тут, мне кажется, есть проблема. Каждый Актор может передавать только immutable сообщения. Передавая сообщение, которое содержит ссылку на объект, мы получаем вероятность того, что объект по этой ссылке будет изменен из двух разных потоков: первого Актора и Актора-получателя. В одной реализации при передачи объектов их сериализовали. Но там я не нашел каким-образом они восстанавливают адреса на других акторов на конечной стороне сообщения.
E>Другой важной характеристикой модели акторов является локальность. Локальность означает, что при обработке сообщения актор может отправлять сообщения только по тем адресам, которые он получил из этого сообщения, по адресам, которые он уже имел до получения сообщения, и по адресам, которые он создал при обработке сообщения.
E>Другими словами, Актор должен знать, кому он отправляет сообщение.
Это откуда такое?
E> Сейчас у меня сделано так: Есть интерфейсы Актора IAgent, простого сообщения IMessagе, запроса и ответа IRequest и IReply. Последние три — вообще не имеют методов, и используются как параметры для методов IAgent. Снаружи используется только IAgent и обращаться к объекту-Актору мы можем только через этот интерфейс. Акторы реализуют два метода простой отправки и запроса с ожиданием ответа (с таймаутом). Таким образом, мы можем отправлять любые сообщения, запрашивать любые данные, главное, чтобы объекты сообщения, запроса и ответа были immutable и реализовывали соответствующие интерфейсы. Обработает ли Актор сообщение или ответит ли на запрос, зависит от конкретного Актора. Каждый Актор регистрирует соответствующий тип сообщений, запросов и ответов и их обработчики. Вот так правильно сделано?
Я не уверен, что существует "каноническое" решение, относительно которого можно мерить "правильно"/"неправильно". Я обычно на OSGI ориентируюсь, на мой взгляд это сейчас наиболее крупное и промышленное использлвание actor model.
E>Тут, мне кажется, есть проблема. Каждый Актор может передавать только immutable сообщения. Передавая сообщение, которое содержит ссылку на объект, мы получаем вероятность того, что объект по этой ссылке будет изменен из двух разных потоков: первого Актора и Актора-получателя. В одной реализации при передачи объектов их сериализовали. Но там я не нашел каким-образом они восстанавливают адреса на других акторов на конечной стороне сообщения.
Обычно это решается copy-on-write. Так, например, в Qt реализовано.
Здравствуйте, Eye of Hell, Вы писали:
EOH>Это откуда такое?
Так Википедия же
E>> Сейчас у меня сделано так: Есть интерфейсы Актора IAgent, простого сообщения IMessagе, запроса и ответа IRequest и IReply. Последние три — вообще не имеют методов, и используются как параметры для методов IAgent. Снаружи используется только IAgent и обращаться к объекту-Актору мы можем только через этот интерфейс. Акторы реализуют два метода простой отправки и запроса с ожиданием ответа (с таймаутом). Таким образом, мы можем отправлять любые сообщения, запрашивать любые данные, главное, чтобы объекты сообщения, запроса и ответа были immutable и реализовывали соответствующие интерфейсы. Обработает ли Актор сообщение или ответит ли на запрос, зависит от конкретного Актора. Каждый Актор регистрирует соответствующий тип сообщений, запросов и ответов и их обработчики. Вот так правильно сделано?
EOH>Я не уверен, что существует "каноническое" решение, относительно которого можно мерить "правильно"/"неправильно". Я обычно на OSGI ориентируюсь, на мой взгляд это сейчас наиболее крупное и промышленное использлвание actor model.
И еще, мне очень интересен такой вопрос. Как должен работать процесс запрос-ответ в модели Акторов. Должен ли "спрашивающий" ждать ответа некоторое время (по таймауту считать что ответа не было) или отправив запрос должен перейти к другим вычислениям? Первый вариант у меня сейчас реализован, и он проще. Отправив IRequest Актор "замирает" и как только придет ответ продолжает работу. Если пришел нулевой ответ (IReplay == null) или же истекло время ожидания, то дальнейшие действия, которые должны были произойти по полученному ответу IReplay, не выполняются. Второй вариант, кажется более правильным. Но в нем мне не совсем понятно, как это все обрабатывать. Ведь ответ может прийти через некоторое время, когда сам Актор уже перешел в совершенно новое состояние. То есть мы отправляем запрос IRequest. Вероятно, нужно зарегистрировать некий обработчик на полученное сообщение IReplay. В момент, когда ответ будет получен, мы ищем нужный обработчик и выполняем его. Как-то так, наверное... Вот, что пишут об этом в вики:
В процессе вычислений, возможно, потребуется отправить сообщение получателю, от которого позже нужно получить ответ. Способ сделать это состоит в том, чтобы отправить сообщение, в котором записан адрес другого актора, называемого возобновлением (иногда его также называют продолжением или стеком вызовов). Получатель может затем сделать ответное сообщение, которое будет отправлено на возобновление.