我开始玩 Actor model ,特别是 Akka.NET .总的来说,我认为我对所有内容都有一个很好的了解,但当然细节决定成败。我正在考虑在现有代码库中采用 Akka.NET,因此我想估计可以保留多少现有抽象。这个想法是可以保留一些特定的高级接口(interface),并且可以编写一些适配器实现来无缝地在 Actor 世界和现有接口(interface)的用户之间来回切换,但我不确定是否推荐这样做以及什么我应该面对的具体问题类型。
简单的例子:
public interface IGetSet<in TK, TV>
{
TV Get(TK key);
void Set(TK key, TV value);
}
public class GetSet<TK, TV> : IGetSet<TK, TV>
{
private readonly ActorRef _getSetActor;
public GetSet(ActorRefFactory system)
{
_getSetActor = system.ActorOf(Props.Create(() => new GetSetActor()));
}
public TV Get(TK key)
{
var x = _getSetActor.Ask<TV>(new GetSetActor.Get(key));
return x.Result; //blocking, I know, it's just an example
}
public void Set(TK key, TV value)
{
_getSetActor.Tell(new GetSetActor.Set(key, value));
}
class GetSetActor : ReceiveActor
{
readonly Dictionary<TK, TV> _values = new Dictionary<TK, TV>();
public class Get
{
public Get(TK key) { Key = key; }
public TK Key { get; private set; }
}
public class Set
{
public Set(TK key, TV value) { Key = key; Value = value; }
public TK Key { get; private set; }
public TV Value { get; private set; }
}
public GetSetActor()
{
Receive<Get>(g => Sender.Tell(_values[g.Key], Self));
Receive<Set>(g => _values[g.Key] = g.Value);
}
}
}
...
var gs = new GetSet<string, int>(ActorSystem.Create("Wasp"));
gs.Set("a", 42);
var i = gs.Get("a");
在这种情况下,IGetSet
接口(interface)来自传统世界,它的实现让我们可以在actors 世界 中来回转换。我试图与 Actor 保持友好关系,他们从未以不同于消息传递的方式使用,所以总的来说这个(当然是微不足道的)练习看起来很有希望,但我想知道从今天开始我是否还有什么需要注意的1.
我一直在阅读关于避免额外的非基于参与者的异步代码对参与者的状态采取闭包的内容,这很清楚,但我没有这样做,但也许还有更多我看不到的内容。我的最终目标是相当广泛地使用这种模式,直到我编写 Rx 的 ISubject
的面向参与者的实现(顺便说一句,我已经做到了,这很容易,但我还是不确定我对所有我应该做的事情都给予了足够的关注)。
我还阅读了一些关于 Typed Actors 的内容,但我不是 Scala 专家,所以我可能没有掌握代码示例中的所有细节,而且我不确定它们是否已经在 Akka.NET 中可用 ( doc page is a 404 )
最佳答案
这看起来不错。 您应该考虑的是,默认情况下,Actor 有“最多一次” 的交付保证,因此,您应该考虑到在与您的 actor 通信时,您可能不会收到回复. (网络故障、远程节点崩溃等)
在本地系统中,消息丢失的可能性很小,但从理论上讲,如果有人对它做了一些过于疯狂的事情,actor 系统可能会崩溃,因此 actor 会死亡。
因此,当使用 Ask
与 actor 通信时,最好确保安全并提供超时并处理该异常,而不是永远阻塞/等待。
从最新的预发布位(1.0 版之前)开始支持异步/等待。
然而,这不是推荐的方法。最好坚持使用 PipeTo
并且要明确。
另一件可能会变得不确定的事情是,因为在您的示例中,您将 Actor 视为键值存储,这一切都很好。
而且你的消息也是不可变的,这也很好。
但是如果 Key 或 Value 属性是 ref 类型,人们可以从外部改变它们,例如IGetSet
的消费者可能会在 actor 内部导致 RC 问题,因为 actor 可能会在另一个线程改变它们时读取这些值..
ActorSystems
也相当昂贵,尽量避免启动许多系统,目标是每个进程一个系统。
除此之外,一切顺利。
关于c# - Akka.NET 参与者和包装器(可能与 Rx 一起使用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29473443/