【问题标题】:Akka.NET actors and wrappers (potentially with Rx)Akka.NET 参与者和包装器(可能与 Rx 一起使用)
【发布时间】:2015-06-10 23:29:27
【问题描述】:

我开始使用Actor model,尤其是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 接口来自传统世界,它的实现让我们可以在演员世界中来回转换。我试图与演员相处融洽,这些演员的使用​​方式与消息传递不同,所以总的来说这个(当然是微不足道的)练习看起来很有希望,但我想知道从那天起我是否还有什么需要注意的1.

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

我还阅读了一些关于 Typed Actors 的信息,但我不是 Scala 专家,所以我可能没有掌握代码示例中的所有细节,而且我不确定它们是否已经在 Akka.NET 中可用(doc page is a 404)

【问题讨论】:

    标签: c# system.reactive actor akka.net


    【解决方案1】:

    这看起来不错。 您应该考虑的是,actor 默认情况下具有“最多一次” 的交付保证,因此,您应该考虑到在与您的actor 通信时,您可能不会收到回复. (网络故障、远程节点崩溃等)

    在本地系统中,消息丢失的可能性很小,但理论上,如果有人对它进行过于疯狂的操作,则参与者系统可能会崩溃,从而导致参与者死亡。

    因此,当使用Ask 与参与者通信时,最好确保安全并提供超时并处理该异常,而不是永远阻塞/等待。

    从最新的预发布位(1.0 之前)开始支持异步/等待。 然而,这不是推荐的方法。最好坚持使用PipeTo 并明确表达。

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

    ActorSystems 也相当昂贵,尽量避免启动多个系统,每个进程争取一个系统。

    除此之外,你很高兴。

    【讨论】:

    • 非常感谢,我会注意您的建议并继续努力 :) 如果您还有一分钟,Typed Actors 的当前计划是什么?它们会在 1.0 中完全可用吗?
    • TypedActors 仍然存在,但它们与 JVM 中的不同,JVM 中的类型化actors 在结构上与 Orleans 中的actors 有点相似。 Akka.NET 中的类型化 Actor 更像是 CQRS 命令处理程序。但是是的,它们仍然受支持
    • @Roger 您在之前的回答中提到的“RC 问题”是什么意思?
    • @wonderfulworld 比赛条件en.wikipedia.org/wiki/Race_condition(有点晚了,但我才看到)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    相关资源
    最近更新 更多