本文已.Net语法为主,同时写有Scala及Java实现代码

严肃的说,演员是一个广泛的概念,作为外行人我对Actor 模型的定义:

  Actor是一个系统中参与者的虚拟人物,Actor与Actor之间是可以相互沟通,所有的沟通都是通过Message

比如说一个呼叫中心,数以百万计的客户可能会呼叫一个1-800的号码,并与许多可能的客户服务代表进行对话

向这样类型的交互可以使用演员建模

在Actor模型中,一切都是Actor,就想在面向对象编程(OOP)中一切都是"Object"一样.在OOP中,你需要使用类和对象进行建模,在Akka中,你可以使用Actor和Message进行建模

以下是Akka中基本例子

using System;

using Akka.Actor;

namespace ActorsSendingMessages

{

/// <summary>

/// 在Akka.NET中Actor都继承于UntypedActor。/// </summary>

public class BasicActor : UntypedActor

{

protected override void PreStart()

{

}

protected override void PreRestart(Exception reason, object message)

{

}

protected override void OnReceive(object message)

{

//handle messages here

}

protected override void PostStop()

{

}

protected override void PostRestart(Exception reason)

{

}

}

}

什么是Message

可能已经注意到了BasicActor中定义的方法

.Net
protected override void OnReceive(object message)
{    //handle messages here

}

该OnReceive方法是Actor接收Message的地方,在Akka中,一个Message就是一个Object,Message可以是任意类型的实例

Actor通常只能处理特定类型的Message,如果Actor收到无法处理的Message,则不会触发任何异常,一般只是将Message标记为"unhandled"
Message是不变的

什么是"不可变"的对象呢?

  不可变对象:是一个对象中的状态(即该对象在内存中的内容)一旦被实例化就不能修改

类似于String类型(.net中 string)

  不可变的Message本质上是线程安全的.没有线程可以修改不可变Message的内容,所以接收到原始Message的第二个线程不必担心以前的线程有修改Message的可能

因此,在Akka中,所有消息都是不可变的,线程也是安全的,这也是为什么可以让上千万Akka的Actor同时处理消息的原因之一.正式不可变的Message消除了同步机制和其他不必要的代码

Actor的行为

我们大概了解了Actor和Message,那这些如何用?

Actor通过Message进行通信

在OOP中,对象通过函数调用与其他对象进行通信.A类在B类上调用一个函数,并等待该函数返回,然后A类可以继续其余工作.在Akka和Actor模型中,Actor之间通过Message进行通信

那有什么特别的呢?

  对于初学者来说,消息传递是异步的,发送Message的Actor可以在接收的Actor处理发件人的Message时继续执行其他工作.所以Actor之间的互动,默认情况下都是异步的

还有另一个变化

  由于所有"函数调用"都被Message代替,即对象的不同实例,因此Actor可以存储其函数调用的历史记录,甚至延迟处理一些函数调用

想象一下,如何使用一个Actor来构建像Microsoft Word中的“撤消”按钮这样的功能?默认情况下,你有一个Message代表每个人对文档所做的更改.要撤消其中一个更改,只需要将消息从UndoActor的垃圾邮件中删除,并将该更改推送回管理Word文档的当前状态的另一个Actor。在实践中这是一个非常强大的概念。

Actor发送Message到地址,而不是直接发送给Actor

位置透明

  什么是位置透明,位置透明意味着无论在何时向Actor发送Message,都不需要知道他们在系统中的位置,可能这个Message覆盖数百台计算机,所以只需要知道Actor的地址.

就像给别人打电话一样,你只需要知道电话号码,其他的电信供应商就会帮你连通.

Actor的工作方式也是一样,每个Actor都包含了以下部分地址

Protocol(协议):就像网络上使用的Http和Https一样,Akka支持多种传输协议用于进程间的通信.单进程Actor系统默认协议是akka://如果使用的远程或者集群,则通常会使用akka.tcp://或者akka.udp://在节点之间进行通信

ActorSystem(Actor系统):在akka的每个ActorSystem实例必须在启动时赋予一个名称,该名称可以由所有参与分布式的多个进程或者计算机共享ActorSystem.

Address(地址):如果不使用远程处理,则ActorPath可以省略这一部分,这部分是用来传达用于Actor系统之间的远程通信的具体IP地址/域名和端口信息

Path(路径):这是一个特定Actor在地址上的路径,结构就像一个网站的Url,所有用户定义的actor都是在/user/下

因此,要向Actor发送消息:

.Net

//local actor

var actorRef = MyActorSystem.Selection("/user/myActor");

actorRef.Tell("HI!");

//remote actor

var remoteActorRef = MyActorSystem.Selection("akka.tcp://MyActorSystem@localhost:1001/user/myActor");

remoteActorRef.Tell("HI!");

向远程Actor发送Message就像本地Actor一样,这就是位置透明的意思

发送给Actor地址的所有Message都是放置在属于Actor的"邮箱"中

当向Actor发送Message时,该Message不会直接进入Actor的OnReceive方法.

Message被放置在按照FIFO(先进先出)顺序排列的"邮箱"中,就像C#中Queue<T>(java中LinkedList)数据结构一样.邮箱有一个非常简单的工作,接收和挂起邮件,直到Actor准备好处理它们.

当Actor准备处理Message时,邮箱将把Message推送到Actor的OnReceive方法中,并运行Actor的消息处理方法.

Actor只能一次处理一个Message

Akka中保证参与者处理Message时,Actor的上下文和内部状态都是线程安全的

之所以这样的原因是:

  因为Message是不可变的,所以每个Message的内容本质上是线程安全的

  因为Message是串行处理的,所以更改一个actor的内部状态和上下文都不需要跨多个线程进行同步

因此,一个Actor在它的OnReceive方法退出之前,都无法处理下一个Message.当处理完时,邮箱会将下一个可用的Message推送到OnReceive方法中

Actor可以拥有内部状态

就像任何类一样,Actor可以拥有自己的属性和字段

当一个Actor重启时,actor实例就像我们这个BasicActor类的一个实例一样被销毁并重新创建.

BasicActor创建新的一个实例,通过Props把构造函数的参数传递给新的实例

Actor有一个明确的生命周期

在Actor可以从邮箱中开始处理Message之前,必须由Actor系统进行实例化并运行其生命周期.

Actor被创建并启动,然后会花费大部分时间接收消息,如果不再需要Actor,可以终止或者停止Actor

  如果Actor以外崩溃(即抛出未处理的Exception),Actor的父级将从头开始自动重启Actor的生命周期,而不会丢失仍在Actor邮箱中的剩余的Message

结合之前的例子BasicActor中实现这个生命周期:

  Actor's constructor(构造函数):BasicActor没有中并没有声明,而是使用了默认的构造函数,当然也可以使用任何带参数的构造函数

  PreStart:这是在actor可以开始接收消息之运行,是放置初始化逻辑的好地方,在重启时会被调用

  PreRestart:如果Actor意外失败(即抛出未处理的Exception),Actor的父级会重启Actor

  PostStop:一旦Actor停止并且不再接收消息,就会被调用,这里可以处理清理引用对象,PostStop在Actor重启时不会调用,只有在人为关闭时才调用

  PostRestart:在PreRestart之后,PreStart之前被调用,这是可以处理崩溃错误和诊断报告

每个Actor都有父级,有的有子级

 就像人一样,Actor有父母,有的有祖父母,兄弟姐妹和孩子

 

这意味着每个Actor都必须由其他Actor创建,所以我们代码:

.Net
var actorRef = MyActorSystem.ActorOf(Props.Create<BasicActor>(), "myActor");
actorRef.Tell("HI!");

在/user/根Actor下创建一个新的Actor,新的Actor的路径就是/user/myActor

同样,还可以在BasicActor中创建其他Actor

.Net
protected override void OnReceive(object message)
{    var childActor = Context.ActorOf(Props.Create<BasicChildActor>(), "child1");childActor.Tell("Hi!");
}

这样childActor的路径就是/user/myActor/child1/

父级监督子级

在关于Actor生命周期的部分中,提到了"Actor是由他们的父级进行重启"的概念.这就类似于,每个家长都收到他们孩子发的特别的消息"求助,我要崩溃了".

每个父级都带有默认的SuperviserStrategy对象(可以自定义).该对象决定了如何处理他们的子级Actor的失败.有三种方式:

  Restart:重启失败的Actor,父级默认方式,除非子级在60秒内反复重启

  Stop:永久停止失败的Actor

  Escalate:将决定交给父级的父级处理

当发出一个Restart或者Stop 的Message,受影响的所有的子级包括自己都会重启或者停止.当然,也可以重启失败的Actor的actor家族树整个部分

引荐:https://petabridge.com/blog/akkadotnet-what-is-an-actor/

原文地址:http://www.cnblogs.com/yangleiblog/p/6766197.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

Akka系列---什么是Actor相关推荐

  1. Akka系列(二):Akka中的Actor系统

    Actor模型作为Akka中最核心的概念,所以Actor在Akka中的组织结构也至关重要,本文主要介绍Akka中Actor系统. Actor系统 Actor作为一种封装状态和行为的对象,总是需要一个系 ...

  2. 2021-08-31 转载 Scala Akka 系列文章

    Akka系列总目录 https://www.jianshu.com/c/e3c378a1b865 Akka系列(一):Akka简介与Actor模型 https://www.jianshu.com/p/ ...

  3. Akka系列(六):Actor解决了什么问题?

    这段时间由于忙毕业前前后后的事情,拖更了很久,表示非常抱歉,回归后的第一篇文章主要是看到了Akka最新文档中写的What problems does the actor model solve?,阅读 ...

  4. 【完整代码】Scala AKKA实现两个Actor之间的通信代码示例

    启动程序: package com.zxl.akka.two_actorsimport akka.actor.{ActorRef, ActorSystem, Props}//extends App 可 ...

  5. Akka创建第一个Actor《nine》译

    在项目中添加以下依赖项: 通过了解actor的层次结构和行为,剩下的问题是如何将IoT系统的顶层组件映射到actor.将代表设备和仪表板的Actor放在最顶层可能很诱人.相反,我们建议创建一个代表整个 ...

  6. Akka 指南 之「Actor 模型如何满足现代分布式系统的需求?」

    温馨提示:Akka 中文指南的 GitHub 地址为「akka-guide」,欢迎大家Star.Fork,纠错. Actor 模型如何满足现代分布式系统的需求? 如前一主题「为什么现代系统需要新的编程 ...

  7. 【Akka系列】之 Akka介绍

    本文翻译自https://doc.akka.io/docs/akka/current/guide/introduction.html Akka介绍 Akka是为设计可伸缩和弹性系统(从处理器到网络)提 ...

  8. Akka 系列(五):Java 和 Scala 中的 Future

    随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue,带你走入异步编程的 ...

  9. 《通过C#学Proto.Actor模型》之 HelloWorld

    在微服务中,数据最终一致性的一个解决方案是通过有状态的Actor模型来达到,那什么是Actor模型呢? Actor是并行的计算模型,包含状态,行为,并且包含一个邮箱,来异步处理消息. 关于Actor的 ...

最新文章

  1. Hystrix 熔断降级
  2. 用好这7个VS Code插件,前端编程效率蹭蹭涨
  3. MySQL 8.0 安装部署3个注意事项
  4. Mac实时远程抓Ubuntu的网络包
  5. 《Act with Prudence》读后感
  6. linux docker 安装sql,CentOS7使用Docker安装SQL Server 2017
  7. Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 prometheus 监控
  8. 解析Web应用服务四大弱点
  9. Mean filter 和 Gaussian filter对比
  10. 中兴linux下载软件,最新中兴新支点操作系统v3.2.2 最新版下载地址电脑版-CC软件...
  11. KPI and evaluation decouple verification
  12. axios和ajax怎么读,axios, ajax和fetch的比较
  13. mcdf项目验证总结-SV
  14. 从“穷逼VIP”论注释规范,你见过哪些奇葩的注释?
  15. Mac地址多少位(48位的(6个字节)) IP多少位
  16. 第一章 初探Swing
  17. ccf 201612-3 权限查询(100分)
  18. 什么是有限状态机FSM
  19. 谷歌游览器打开pdf总是提示要另存为
  20. python做一个考试系统_python考试系统 相关实例(示例源码)下载 - 好例子网

热门文章

  1. 设置utf8编码问题
  2. 能源项目xml文件 -- app-context.xml
  3. 3月更新来了!Windows 11正式版22000.556发布
  4. .NET6之MiniAPI(四):配置
  5. C#位图BitArray 小试牛刀
  6. 更新两个WPF开源项目
  7. 联想继续为其硬件产品完善Linux支持
  8. 你可能不知道的按位与、或运算技巧
  9. 如何在 ASP.Net Core 中使用 Serilog
  10. 如何在 C# 中使用 反射