开源并发框架,Skynet 1.0.0 RC 版发布

jopen 8年前

拖了很久,终于决定给 skynet 1.0.0 封版了。比预期的时间 足足晚了半年,好在还是在 2015 年把这个事情启动了。

其实已经很久没有对已有特性做修改了,如果的项目是在今年 3 月份以后跟进的 1.0 alpha 版的话,升级到目前的最新版本应该不会有太大痛苦。最近几个月几乎没有增加新的特性,反而是在裁减一些多余的,用的人不多的东西(为了兼容,把这样一些 API 移到了一些独立的模块中,方便废弃)。

据我所知,skynet 用于的商业游戏项目(以及一些非游戏项目)早已经超过了 2 位数,收获了不错的口碑。它不再是我们自己公司的内部项目,持续收到不同人的 PR 说明很多同学不仅仅在使用,更是用心在 review 代码,让它真正成为一组公众视野下的代码。我相信这是开源的终极意义:众目睽睽之下, Bug 无所遁形。

我们自己的项目也从 skynet 开源经营中获益良多。有好几处来源于外部的 bugfix 都是在错误发生前被堵住,只是可惜的是,我们也有项目未能及时跟进,只到真的出错了才回头发现在主干上早已改过。这些事故反而证明了开源对于提高项目质量的作用。

这次发布 1.0.0 正式版本的候选版 (RC) ,并专门公告,就是希望有在使用 skynet 的同学,尤其是已经有项目上线运营的,能够在最后这几天将遗留问题提出来,issue 或 pr 都可以。不要把遗憾留到 1.0.1 :)

我希望这次把 RC 标签保留一个月,在农历新年前换成正式版。


对于因为 skynet 常年挂着 alpha (其实 beta 已经一个月了)标签还在犹豫的同学,希望换上正式版标签后可以打消你的疑虑(当然,我个人并不觉得标签换了后,代码质量会有本质变化)。

同时不要再不断的问 “真的有项目用 skynet 的吗?”,“skynet 有文档吗?”。

尤其对于后一个问题,我对连 README 都不看的同学,真的很烦回答啊。

skynet 不仅有 FAQ ,也有中文的文档,而且文档更新的还很及时。麻烦你读一下 readme 以及跟着链接去看看 wiki 吧,能问出 skynet 有文档吗这种问题的同学,我相信把文档摆在他面前也是读不下去的,文档对他就没有存在意义。


算起来从 2012 年 8 月开源发布(7 月开始写第一行代码)到现在居然已经有 3 年有余。这么一个小小的项目经历了三年,整个过程都有线上运营的项目在紧跟。为了历史兼容问题,必然有无数遗憾。传言 linus 说过,所有项目你都要做两次才明白到底怎么做。

我不知道有没有机会重新来做 skynet 2.0 (目前没有任何这方面的计划),把我认为错误的设计,更好的设计推倒重来一次。至少可以把项目的代码风格统一一点,看起来更漂亮。

但眼下要做的事情仅仅只是:赶紧发布第一个稳定版,让更多的人放心来用。用的人越多,后来人也就越放心。


Skynet 是一个基于 Actor 模式的开源并发框架。

skynet 节点,通过 master ,认识网络中所有其它 skynet 节点。它们相互一一建立单向通讯通道。也就是说,如果一共有 100 个 skynet 节点,在它们启动完毕后,会建立起 1 万条通讯通道。

这个系统是单进程多线程模型。

每个内部服务的实现,放在独立的动态库中。由动态库导出的三个接口 create init release 来创建出服务的实例。init 可以传递字符串参数来初始化实例。比如用 lua 实现的服务(这里叫 snlua ),可以在初始化时传递启动代码的 lua 文件名。

每个服务都是严格的被动的消息驱动的,以一个统一的 callback 函数的形式交给框架。框架从消息队列里取到消息,调度出接收的服务模块,找到 callback 函数入口,调用它。服务本身在没有被调度时,是不占用任何 CPU 的。框架做两个必要的保证。

一、一个服务的 callback 函数永远不会被并发。

二、一个服务向两一个服务发送的消息的次序是严格保证的。

我用多线程模型来实现它。底层有一个线程消息队列,消息由三部分构成:源地址、目的地址、以及数据块。框架启动固定的多条线程,每条工作线程不断的 从消息队列取到消息。根据目的地址获得服务对象。当服务正在工作(被锁住)就把消息放到服务自己的私有队列中。否则调用服务的 callback 函数。当 callback 函数运行完后,检查私有队列,并处理完再解锁。

线程数应该略大于系统的 CPU 核数,以防止系统饥饿。(只要服务不直接给自己不断发新的消息,就不会有服务被饿死)

由于我们是在同一个进程内工作的。所以我对消息传递做了一点优化。对于目前的点对点消息,要求发送者调用 malloc 分配出消息携带数据用到的内存;由接受方处理完后调用 free 清理(由框架来做)。这样数据传递就不需要有额外的拷贝了。

来自: http://www.oschina.net/news/69442/skynet-1-0-0-rc