(建议使用桌面端设备查看)
简介
在计算机科学中,演员模型(Actor model)是一种并发运算上的模型。“演员”是一种程序上的抽象概念,被视为并发运算的基本单元:当一个演员接收到一则消息,它可以做出一些决策、创建更多的演员、发送更多的消息、决定要如何回答接下来的消息。
-- Wikipedia
什么是演员框架
演员框架对并发的影响
- 一个演员被当作一个原子类型, 其中的状态不予别人共享, 这就降低了锁的开销.
- 一个演员可以被分配再不同的线程或协程上, 不通过传统的函数调用而是只用消息(Message)投递到彼此的信箱完成信息的交流.
- 不同演员之间的消息处理可以随意并行化因为不涉及依赖关系.
天生异步的设计
- 一条消息只要到达信箱就有朝一日能处理, 处理之后就会把结果发到别人的信箱.
- 演员系统像事件循环一样随机处理信箱里收到的消息, 从而实现异步性.
现存的优秀的设计
标准库: Erlang OTP
这可是老祖宗级别的, 而且所有的演员模型框架借鉴的始祖.
- 分布式运算
- 高故障容许度
- 软性即时运算
- 高可用性 不停运作的应用热插拔
普通库: Scala Akka
虽然没有Erlang那么动态, 可以这么灵活, 也可以无惧错误但是他有以下几个优点:
- JVM优秀的底层IO
- Scala丝滑的语法糖
- 超高的可定制性(如邮箱, 派发机制, 消息路由等)
语言: Pony lang
这是一个新兴的编程语言, 所以历史包袱比较少.
- 演员模型
- 比Rust更加复杂的借用检查机制
- 通过静态编译和演员模型带来的极低延迟和极大吞吐
Rust中现有的演员框架的优缺点:
Actix: Rust里最老牌的Actor框架
作为孵化出顶级项目 Actix-web , Actix 肯定是有两把刷子的, 我在刚刚开始使用Rust, 远在 Rust async 连提案还在吵得热火朝天的时候, actix已经开始产出一些优秀的项目了.
但现在 Actix 最大的缺点就是 CodeBase 非常庞大, 有很严重的历史包袱, 对 Tokio 1.0 以后的运行时的支持缓慢等, 最大的问题应该就是这套接口很多都不是异步时代的标准.
使用Actix写的最小的Actor
我们可以看到首先就是定义struct, 然后impl Actor, 然后指定Context类型, 然后写message和message的handler
Xactor: Async-std 时代后的新秀
当时间到达了 async-std 时代, async 代码已经成为了标准, 而async 代码天生有对 codebase的污染性, 另外就是 Rust 语言的 async 设计保证了 async 的并发性, 所以 xactor 通过大幅精简架构使得在所有 actix 主流功能都保持的前提下可以使用异步代码并带来性能上的提升.
但是缺点就是这个库看起来并不活跃了, 而且这个库的很多代码看起来缺乏测试, 有一些代码看上去可扩展性不足, 有一些看上去非常的简陋.
我们用下面的两个图片举个例子为什么我们说他简陋:
Xtor的监督者
Erlang OTP的文档
可见你的代码还没人文档描述的行为多...
我另起炉灶的原因:
原因是这样的, 我们公司在进行架构重构的时候要把所有的RPCClient的代码进行重构成异步, 但是中间设计到一些service的使用, 然后我在进行迁移的时候遇到了Actix很多的问题, 因为有一些Service需要异步代码, 异步代码天生具有可传染性, 然后我需要在actor里面使用tokio进行block_on操作, 这简直就是脱了裤子放屁, 还有就是一些包装并不能够直接放到actor的handler里面比如开一个tokio system这种东西, 能直接把Actix扬了, 所以我重造了.
现在这个项目已经迁移到公司的org下面了
这个框架最大的不同就是在于Addr是弱类型的, 这是我做的一个取舍, 别喷, 性能没你们想象的那么烂.
只要Addr是弱类型的我们就可以做到:
- 使用supervisor监控不同的东西
- 一个东西可以被多个supervisor进行监督
- supervisor也是一个actor
- message broker也是一个actor
- supervisor本身也可以被supervise
- 可以使用actor的message handler做delegate(写过C#都知道我在说什么)
所以可见好处还是大于缺点的.
评测数据
CPU: I7 11700k, RAM: DDR4 3200Mhz, OS: Windows 11
使用的配置
Xtor: 10.01ms
Actix: 12.73ms
Xactor: 10.80ms
可见这个项目的初期就已经有不错的收益了, 我甚至打败了老牌Actix, 然后我们再看这个性能曲线是一个完整的正态分布, 也就是说这个锁处理也非常的到位, 反观xactor应该是出现了没抢到的情况因为有大量outlier.
还是希望大家多来贡献代码吧~
谢谢哦!