简体   繁体   English

Akka.NET演员和包装器(可能与Rx)

[英]Akka.NET actors and wrappers (potentially with Rx)

I started playing with the Actor model , and in particular with Akka.NET . 我开始玩Actor模型 ,尤其是Akka.NET Overall I think I have a good idea of what's all about, but of course the devil is in the detail. 总的来说,我认为我对所有内容都有一个很好的了解,但当然魔鬼在细节上。 I was thinking about adopting Akka.NET in an already existing codebase, and therefore I'd like to estimate how much of the existing abstractions can be kept. 我在考虑在现有的代码库中采用Akka.NET,因此我想估计可以保留多少现有的抽象。 The idea is that some specific high-level interfaces could be kept, and some adapter implementations would be written to seamlessly go back and forth across the actors world and the users of the existing interfaces, but I'm not sure if that's recommended and what types of specific problems I should expect to face. 我们的想法是可以保留一些特定的高级接口,并且可以编写一些适配器实现以在演员世界和现有接口的用户之间无缝地来回传递,但是我不确定是否推荐了这些接口我应该面对的具体问题类型。

Trivial example: 琐碎的例子:

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");

In this case the IGetSet interface comes from the traditional world , and its implementation lets us transition back and forth with the actors world . 在这种情况下, IGetSet接口来自传统世界 ,它的实现让我们可以与演员世界来回转换。 I tried to be nice with actors, which are never used in ways different from message passing, so overall this (trivial, of course) exercise looks promising, but I'd like to know if there's anything more I should pay attention to since day 1. 我试图与演员很好,从来没有使用过与消息传递不同的方式,所以整体来说这个(当然是微不足道的)练习看起来很有希望,但是我想知道从那天开始我还有什么需要注意的。 1。

I've been reading about avoiding additional non-actor-based async code taking closures on actors' state, that's clear and I'm not doing it, but maybe there's more which I can't see. 我一直在阅读关于避免额外的基于非演员的异步代码对演员的状态进行封闭,这很清楚而且我没有这样做,但也许还有更多我看不到的东西。 My final goal is to use this pattern quite extensively, down to point I'd write actor-oriented implementations of Rx's ISubject (which BTW I already did and it was easy, but again I'm not sure I paid enough attention to all I should). 我的最终目标是非常广泛地使用这种模式,直到我会编写Rx的ISubject演员导向实现(我已经做过BTW,这很容易,但我再也不确定我是否对所有我都给予足够的重视应该)。

I also read a bit about 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 ) 我也读过一些关于Typed Actors的内容 ,但我不是Scala专家,所以也许我没有抓住代码示例中的所有细节,而且我不确定它们是否已经在Akka.NET中可用( doc page is一个404

This looks good. 这看起来不错。 What you should take into account is that actors have a delivery guarantee of "at most once" by default, so, you should take into account that when communicating with your actor that you might not get a response back. 您应该考虑的是,默认情况下,演员有“最多一次”的交付保证,因此,您应该考虑到与您的演员沟通时可能无法获得回复。 (Network failure, crashed remote nodes and such) (网络故障,崩溃的远程节点等)

In a local system, it's very unlikely that a message would get lost, but in theory, the actor system could crash if someone does something too wild with it, and thus the actors die. 在本地系统中,消息不太可能丢失,但从理论上讲,如果某人做了过于狂野的事情,演员系统可能会崩溃,从而演员死亡。

So when communicating with an actor using Ask better be safe and provide a timeout and handle that exception instead of block/wait forever. 因此,当使用Ask与演员进行通信时,最好是安全并提供超时并处理该异常而不是永久阻止/等待。

Async/Await is supported as of the latest pre release bits(pre 1.0). 从最新的预发布位(1.0之前版本)开始支持Async / Await。 It is however not the recommended approach. 然而,这不是推荐的方法。 better stick with PipeTo and be explicit. 更好地坚持使用PipeTo并明确。

Another thing that could get iffy is since in your example you are treating the actor as a Key Value store, which is all fine. 另一件可以获得iffy的事情是,因为在你的例子中你将actor视为Key Value商店,这很好。 And your messages are also immutable, which is also good. 而且你的消息也是不可变的,这也很好。 But if the Key or Value properties are ref types, and people can mutate those from the outside, eg the consumers of IGetSet that could cause RC problems inside the actor as the actor might read those values when another thread is mutating them.. 但是如果Key或Value属性是ref类型,并且人们可以从外部改变那些,例如IGetSet的消费者可能导致actor内部的RC问题,因为当另一个线程正在改变它们时,actor可能会读取这些值。

ActorSystems are also quite expensive, try to avoid spinning up many systems, aim for one system per process. ActorSystems也非常昂贵,尽量避免使用多个系统,每个进程的目标是一个系统。

Other than that, you are good to go. 除此之外,你很高兴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM