从实习到现在,一直在做Unity相关的业务,不知不觉中感觉已经不在关注服务器相关的技术了。一次偶然的机会再腾讯的gad平台上观看了云风在15年在腾讯做的skynet讲座(http://gad.qq.com/content/coursedetail/467),skynet是用c写的核心,lua做上层业务,基于actor模型的服务器框架,哈哈,这次学习actor模式的学习也是因此而起。
Actor模型概念
Actor模型为并行而生,简单说是未解决高并发的一种编程思路。在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接发送消息,不需要经过什么中介,消息是异步发送和处理的。在Actor模式中,“一切皆是Actor”,所有逻辑或者模块均别看做Actor,通过不同Actor之间的消息传递实现模块之间的通信和交互。Actor模型描述了一组为了避免并发编程的常见问题的公理:
1.所有Actor状态是Actor本地的,外部无法访问。
2.Actor必须只有通过消息传递进行通信。
3.一个Actor可以响应消息:推出新Actor,改变其内部状态,或将消息发送到一个或多个其他参与者。
4.Actor可能会堵塞自己,但Actor不应该堵塞它运行的线程。
Actor优点、缺点分析
传统的并发编程方式大都使用“锁”的机制,相信大多数都是”悲观锁“,这里几乎可以断定会出现两个明显的问题:
1.随着项目体量增大,业务愈加复杂,不可避免大量使用“锁”,然而大家都知道“锁”的机制其实很耗性能的,所以大量使用锁的机制肯定会造成效率不高
2.即使大量依赖“锁”解决了系统中资源竞争的情况,但是由于没有一个规范的编程模式,最后系统的稳定性肯定会出问题,最根本的原因是没把系统的任务调度抽象出来,由于任务调度和业务逻辑的耦合在一起,很难做一个很高层的抽象,保证任务调度有序。
3.难以维护等等弊端
上面是传统通过“锁”的机制实现并发编程的缺点,然而Actor为什么一定层度上可以解决这些问题呢?个人认为其最根本的原因是Actor模式下提供了一种可靠的任务调度系统,也就是在原生的线程或者协程级别上做了更高层次的封装。这会给编程模式带来巨大的好处:
1.由于抽象了任务调度系统,那么就可以使系统的线程调度可控,易于统一处理,稳定性和可维护性好
2.作为开发者我们只需要关心每个Actor的逻辑就可以了,避免“锁”的“滥用”
3.Actor也提供了很多基本准则,避免了很多并发编程中的问题
……
那么Actor没有缺点吗?那也不是,比如当所有逻辑都跑在Actor中时,很难掌控Actor的粒度,稍有不慎就可能造成系统中Actor个数爆炸的情况,Actor当出现必须共享数据或者状态时就很难避免使用“锁”,但似乎由于上面的“Actor可能会堵塞自己,但Actor不应该堵塞它运行的线程”准则冲突,哈哈,这个时候也许可以选择使用redis做数据共享