2018年12月18日 17:26
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

Akka是一组开源库,用于设计跨处理器核心和网络的可扩展弹性系统。Akka允许您专注于满足业务需求,而不是编写低级代码以提供可靠的行为,容错和高性能。    

Akka有什么特点呢?多线程行为,不使用像atomics或locks这样的低级并发结构。您甚至不需要考虑内存可见性问题。系统及其组件之间的透明远程通信,您不需要编写或维护困难的网络代码。集群,高可用性架构,具有弹性,可按需扩展或扩展。接下来我们就实践一把这个akka组件,首先VS项目安装一下包

image.png

安装完成后,我们新建一个winform项目,开始。这里我设计一个学校打扫卫生的案例,有三种演员,第一个是班长,第二个是劳动委员,第三个是全班其他学生们。当向班长发布打扫卫生的命令后,班长通知劳动委员。劳动委员告诉大家开始打扫卫生,大家收到消息后开始打扫。当向班长发布停止打扫的命令后,班长通知劳动委员。劳动委员告诉大家停止打扫卫生,大家收到消息后停止打扫卫生。

首先定义这三个演员actor模型。

internal class StudentActor : ReceiveActor
{
    IActorRef laborLeaderActor;

    public StudentActor()
    {
        laborLeaderActor = Context.ActorOf(Props.Create<LaborLeaderActor>(), "LaborMember");
        Receive<string>(message =>
        {
            Sender.Tell(message); ;
            laborLeaderActor.Tell(message);
        });
    }
}

internal class LaborLeaderActor : UntypedActor
{
    private IActorRef child;
    protected override void PreStart()
    {
        Console.WriteLine("Labor leader coming...");
        child = Context.ActorOf(Props.Create<LaborMemberActor>(), "LaborMember");
    }

    protected override void PostStop() { Console.WriteLine("Labor Leader:Labor Stop"); }

    protected override void OnReceive(object message)
    {
        switch (message.ToString())
        {
            case "stop":
                    Context.Stop(Self);
                Context.Stop(child);
                break;
            case "labor":
                Console.WriteLine("Labor Leader: Labar,Labar,quickly!");
                child.Tell("labor");
                break;
        }
    }
}

internal class LaborMemberActor : UntypedActor
{
    protected override void PreStart()
    {
        Console.WriteLine("Labor member coming...");
    }

    protected override void PostStop() { Console.WriteLine("Labor Member: Stop,Stop,Stop,Stop....."); }

    protected override void OnReceive(object message)
    {
        switch (message.ToString())
        {
            case "stop":
                Context.Stop(Self);
                break;
            case "labor":
                Console.WriteLine("Labor Member: Labar,Labar,Labar,Labar.....");
                break;
        }
    }
}

这三个模型建好之后,我们开始打扫卫生,首先我们创建一个演员班长。

private void btnStart_Click(object sender, EventArgs e)
{
    var system = ActorSystem.Create("SchoolSystem");
    var monitor = system.ActorOf<StudentActor>("monitor");
    monitor.Tell("labor");
}

现在我们向班长发出劳动的命令,班长收到消息后,告诉劳动委员开始打扫卫生。这里其实班长这个演员又把消息通知给了其他演员劳动委员。其实也是Parent/Child的关系。

zlaborLeaderActor.Tell(message);

然后劳动委员LaborLeaderActor又把消息通知给全班学生。

case "labor":
   Console.WriteLine("Labor Leader: Labar,Labar,quickly!");
   child.Tell("labor");

全班同学收到打扫卫生的消息后,开始打扫,最后执行的结果如下。

image.png

当班长收到通知后,通知下去以后,劳动委员Labor leader来了,全体学生来了。来了后劳动委员告诉大家快劳动,大家收到命令后,开始劳动,劳动......。上面这些就是一个发布打扫卫生的流程,相比以前的传统写法,这种基于消息通知的架构是不是扩展性更好,耦合度更低,所有交互都是通过发送消息来解决。

举个例子,年底了,你想让别人还你钱,你得先实例化一个还钱人,然后调用他的支付方法,他才能把钱还给你。在actor模型下,欠钱人就是个演员,你发消息告诉他还钱。你完全不需要关注他是否有支付方法,至于我发消息过去,还不还那是由我们自己设计的。就像上面班长发布命令打扫卫生,劳动委员这里如果没有设计通知大家的话,那其实这个流程是走不下去的。

接下来我们再看一下停止打扫卫生。

private void btnStop_Click(object sender, EventArgs e)
{
    var system = ActorSystem.Create("SchoolSystem");
    var monitor = system.ActorOf<StudentActor>("monitor");
    monitor.Tell("stop");
}

其实执行过程和上面一样,给班长发布停止命令后,班长通知劳动委员停止劳动,劳动委员停止自己和全体同学的劳动。

image.png

Context.Stop(Self);
Context.Stop(child);

在这里我们看到我们的代码是先停止自己,再停止child,可是执行结果却是先停止了child,再停止自己。很好理解,手下人都没停,自己肯定不能停,因为你是领导。

OK,今天就到这,后面会持续学习这个组件,今天不过看了些皮毛而已就先写出来。

发表评论
匿名  
用户评论

匿名游客

2018年12月21日 10:44
老兄,这个写的有点简单,能不能在深入点?