Hive , Lua 的 actor 模型

云风 2013-06-26 19:10

上个周末我一直在想,经过一年多在skynet上的开发,我已经有许多相关经验了。如果没有早期 erlang 版本的历史包袱以及刚开始设计 skynet 时的经验不足,去掉那些不必要的特性后的 skynet 应该是怎样的。

一个精简过代码的 skynet 不需要支持 Lua 之外的语言和通讯协议。如果某个服务的性能很关键,那么可以用 C 编写一个 Lua 库,只让 Lua 做消息分发。如果需要发送自定义协议的消息,可以把这个消息打包为一个 C 结构,然后把 C 结构指针编码在发送的消息中。

skynet 的内部控制指令全部可以移到一个系统服务中,用 Lua 编写。

跨机支持不是必要的。如果需要在多个进程/机器上运行多份协同工作,可以通过编写一个跨机通讯的服务来完成。虽然会增加一个间接层使跨进程通讯代价更大,但是可以简化许多代码。

广播也不是基础设施,直接用循环发送复制的消息即可。为了必要过大的消息在广播过程中反复拷贝,可以把需要广播的消息先打包为 C 对象,然后仅广播这个 C 对象的指针即可。

基于精简设计的理念,我花了两天时间重新实现了 skynet ,并赋于它新的名字Hive。这次一共不到 2000 行代码,其中 C 代码不到 1400 行,可以说达到我最初精简代码的目的。

对于不了解 skynet 的同学来说,最简单介绍 hive 的方法是,这是一个精简版的 erlang ,用 Lua 实现的 actor 模型。

你可以用标准的 Lua 5.2 解释器包含 hive 模块,并用 hive.start 启动它即可。

main.lua 这个文件会被首先运行,并启动在一个独立的 Lua state 中,这里把这个独立的 state 称为 cell 。同时,系统 system cell 一定存在,它可以向其他 cell 提供 timer 等基础服务。

hive 由很多 cell 构成,每个都是独立的 lua state ,并采用多线程并行工作。线程的总数可以在启动时设定,cell 的个数可以远大于线程数,它们将完全均匀的分配 cpu 资源。

每个 cell 都是一个消息收发器,可以处理别的 cell 发送过来的消息。处理消息可以是严格的请求回应模式,也可以只投递消息而不期待回应。每条消息都由一个独立的 coroutine 来处理。

目前 main.lua 演示了如何启动新的 cell pingpong.lua ,并给它发送消息。

感兴趣的同学可以在 github 上取得全部代码,我列了一个长长的 todo list ,大部分工作是从 skynet 移植过来。这不是一个工作项目,所以不保证最近有精力全部完成它们。如果你有兴趣,可以帮助我一起来完成。

[返回] [原文链接]