Akka.NET 演员和包装器(可能与 Rx 一起使用)

Akka.NET actors and wrappers (potentially with Rx)

我开始玩 Actor model, and in particular with Akka.NET。总的来说,我认为我对所有内容都有一个很好的了解,但当然细节决定成败。我正在考虑在现有代码库中采用 Akka.NET,因此我想估计可以保留多少现有抽象。这个想法是可以保留一些特定的高级接口,并且可以编写一些适配器实现来无缝地在演员世界和现有接口的用户之间来回切换,但我不确定是否推荐这样做以及什么我应该面对的具体问题类型。

简单的例子:

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 界面来自 传统世界 ,它的实现让我们可以与 actors 世界[=] 来回转换=28=]。我试图与演员保持友好关系,他们从未以不同于消息传递的方式使用,所以总的来说这个(当然是微不足道的)练习看起来很有希望,但我想知道从今天开始我是否还有什么需要注意的1.

我一直在阅读有关避免额外的非基于参与者的异步代码对参与者的状态进行闭包的内容,这很清楚,但我没有这样做,但也许还有更多我看不到的内容。我的最终目标是相当广泛地使用这种模式,直到我编写 Rx 的 ISubject 的面向参与者的实现(顺便说一句,我已经做到了,这很容易,但我再次不确定我付出了足够的代价注意我应该做的一切)。

我也读了一些关于Typed Actors, but I'm not a Scala expert so maybe I'm not grasping all the details from the code samples, and I'm not sure they are already available within Akka.NET (doc page is a 404)

这看起来不错。 您应该考虑的是,默认情况下,演员有 "at most once" 的交付保证,因此,您应该考虑到,在与您的演员交流时,您可能无法获得回复。 (网络故障、远程节点崩溃等)

在本地系统中,消息丢失的可能性很小,但从理论上讲,如果有人对它做得太疯狂,actor 系统可能会崩溃,因此 actor 会死。

因此,当使用 Ask 与 actor 通信时,最好保证安全并提供超时并处理该异常,而不是永远 block/wait。

Async/Await 从最新的预发布位(pre 1.0)开始支持。 然而,这不是推荐的方法。最好坚持 PipeTo 并明确。

另一件可能有问题的事情是,因为在您的示例中,您将 actor 视为键值存储,这没问题。 而且你的消息也是不可变的,这也很好。 但是如果 Key 或 Value 属性是 ref 类型,人们可以从外部改变它们,例如IGetSet 的消费者可能会在 actor 内部导致 RC 问题,因为 actor 可能会在另一个线程改变它们时读取这些值..

ActorSystems 也很昂贵,尽量避免启动许多系统,目标是每个进程一个系统。

除此之外,一切顺利。