“使用actor就像租车——我们如果需要,可以快速便捷地租到一辆;如果车辆发生故障,也不需要自己修理,直接打电话给租车公司更换另外一辆即可。”
摘录来自: [美] Paul Butcher. “七周七并发模型。”
什么是actor
actor类似于面向对象(OO)编程中的对象——其封装了状态,并通过消息与其他actor通信。 在面向对象中,我们使用方法调用的方式去传递信息,而在actor中,则使用发送消息去传递信息。
在actor模型中,actor是一个最小的计算单元。
虽然在actor中保留了可变状态,但是其并不和其他actor共享,actor的私有变量不会被其他actor直接更改。
actor模型中遵循以下几个原则:- 所有的计算都是在actor中执行的
- actor之间只能通过消息进行通信交流
- 为了响应消息,actor可以进行下列操作
- 更改状态或行为
- 发消息给其他actor
- 创建有限数量的子actor
actor模型的好处
- 事件驱动模型 - actor使用异步消息的形式进行通信,在发消息后不会因等待回复而阻塞其他工作。
- 强隔离原则 - 和传统的java对象不同,actor不提供公共的api方法供外部调用。相反,其仅通过消息的形式对外提供服务。这样避免了actor之间的任何状态共享;获取一个actor状态的唯一做法就是发一个消息去询问他。
- 位置透明 - 系统使用工厂构建一个actor实例,并返回其引用。由于位置无关紧要,Actor实例可以启动,停止,移动和重启以进行扩容/缩容,或从意外故障中恢复。
- 轻量级 - 每个actor实例仅使用几百bytes,在单个应用程序中可以轻松创建百万个并发的actor。
任其崩溃
在传统的模型中,我们往往会尽可能的考虑到各种情况,对入参格式,类型做各种各样的校验,容错。这样混入了大量业务无关代码,使得代码流程变得复杂,而没有明显错误
actor模型中对异常的遵循为"任其崩溃"哲学。不做防御性逻辑,而是让actor的管理者去处理这些问题。
- 因为actor之间是相互独立的,所以一个actor的崩溃不太可能会影响到其他actor。
- 没有了防御性代码,使逻辑更加简洁且容易理解。
- 由actor管理者可以选择崩溃处理方案,也可以不处理,仅记录崩溃原因。
面对故障,actor管理者有四种不同的可选方案:
- 恢复(Resume)子 Actor,保持其已有的内部状态,但是忽略掉导致故障的消息;
- 重启(Restart)子 Actor,通过启动新的实例,清理其已有的状态;
- 永久停止(Stop)子 Actor,将子 Actor 未来所有的消息发送至 Dead-Letter Office ;
- 将故障传递至更高的层级 (Escalate),这需要让监管者本身也发生故障。
消息
actor之间通过互传消息的形式进行通讯。
actor收到的消息会被暂存于其的一个内部队列中,通常被称为邮箱(mailbox),随后,该actor会以串行的方式处理消息。
actor通过加入mailBox这一中间层的设计,使得actor之间解耦合,且发送消息时不会被阻塞。虽然actor之间可以同时运行,但在单个actor内部,都是以mailBox的顺序依次串行处理消息,且仅当当前消息处理完成后才会处理下一个消息,所以在处理消息时我们并不用关系并发问题。
回复消息
在actor模型中,并没有直接提供回复消息的能力。
所以,我们一般在消息中带上发送方actor的引用,这样,如果接收方需要回复消息的话,可以直接通过消息中的引用回复消息。
参考资料
《七周七并发模型》