看官们肯定还有大部分不是很熟悉Actor模型. 我这里基于Erlang, Skynet等语言和框架库来实战型解释下Actor模型. Actor概念
Actor模型和OO类似, 都是符合人的思维模式进行编码. OO里啥都是类, 用类来模拟对象, 解决所有的问题. Actor类似的使用Actor来模拟处理对象和单元
Actor在Erlang中叫进程(非操作系统进程), 在Skynet中叫svc(服务) Mailbox消息队列
每个Actor中包含有一个mailbox, 也就是邮箱. Actor自己只能通过收发mailbox与外界进行沟通, 也就是说, Actor之间只能通过消息进行互相交流, 不能采用其他形式.
mailbox本身是一个顺序队列, 先进先出. 而且mailbox从理论上说没有上限, 实际上呢, mailbox可能会由于不断的消息堆积导致内存上涨. 这都是正常的.
既然mailbox是队列, 也就代表着一个Actor里的逻辑处理是顺序的, 单线程的. 但Actor群体中每个Actor可以独立处理事务. 因此CPU可以分到每个Actor中进行处理,并发的大业也就奠定了基础. Actor的标识: ID
那么, Actor之间的消息要派发, 怎么定位Actor呢? 使用指针?句柄? 都不是的.
Actor定位使用用ID. 每个Actor有全局唯一的ID, 这里不使用GUID, 因为太难定位了, Erlang选择了一种优雅的方式实现ID. 先吃一个栗子:
0.11 1.2 3.5
这就是Erlang的pid(进程id). 点前面的部分代表的是某个独立域, 在这个域中通过序号标示每个进程的id,序号就是小数点后面的部分
那么, 有了ID, 派发消息就变的很简单了, 看栗子
send( 来源id, 目标id, 发送内容)
有来源id的存在, 是为了回发, 或者虚拟来源. 通信自由与部署无关性
有了Actor模型的存在, 逻辑都是分布式编写, 意思就是挂在每个Actor上来编写. 而由于Actor模型之间只有消息通信, 没有函数调用, 指针之类的本地内容. 因此让Actor的部署变的非常自由. 也就是说, Actor的逻辑, 无需关心自己被部署在1个进程, 还是几台机器. 但是为了内部性能和传输效率的考虑. 能不拆进程, 尽量在同一个进程处理, 能不拆到多台机器, 尽量减少拆到多台机器.
但当你确实需要并发时, 只需要轻松的修改下设置或者少量代码, 整个逻辑就可以跑在分布式集群中了
同步和异步
按照Erlang的处理方式, 默认进程(Actor)间使用send发送消息, 这个过程是异步非阻塞的; 当需要同步处理时, 会使用rpc, 也就是使用call的方式进行同步等待, 等对方进程(Actor)收到并处理消息后, 返回结果后, call的调用才结束.
如果call处理中, 其他的Actor给你发消息时, 消息会一直保存在你的Actor的mailbox中, 这里认为mailbox无限大