开发笔记(16) : Timer 和异步事件
这几天,安排新来的王同学做数据持久化工作。一开始他是将 sharedb 里的数据序列化为文本储存的。这步工作做完后,开始动手把数据放到 Redis 数据库中。我们的系统主干由 Lua 构建,所以需要一个 Lua 的 Redis 库。google 来的那份,王同学不满意。三下五除二自己重写了一个。据说把代码量减少到了原来的三分之一(开源计划我正在督促)。唯一的问题是,如果直接采用系统的 socket 库,不能很好的嵌入我们的整个通讯框架。我们的 skynet 全部是通过异步 IO 自己调度的,如果这个数据服务单方面阻塞了进程,会使得别的进程获得不了时间片。
蜗牛同学打算改进 skynet 增加异步 IO 的支持。
我今天在考虑现有的 API 时候,对比原有的 timer 接口和打算新增加的异步 IO 接口,发现它们其实是同一类东西。即,都是一个异步事件。由客户准备好一类请求,绑定一个 session id 。当这个事件发生后,skynet 将这个 session id 推送回来,通知这个事件已经发生。
在用户编写的代码的执行序上,异步 IO 和 RPC 调用一样,虽然底层通过消息驱动回调机制转了一大圈,但主干上的逻辑执行次序是连续的。
受历史影响,我之前在封装 Timer 的时候,受到历史经验的影响,简单的做了个 lua 内 callback 的封装。今天仔细考虑后发现,我们整个系统不应该存在任何显式的回调机制。正确的接口应该保持和异步 IO 一致:
每个独立服务有一组信息包的分发器,外部来的消息会被并发的处理,每条消息是一个独立的执行序,相互不会被阻塞。同时,服务本身有一个主干执行流程,在启动之初就开始执行,可以认为它响应了一个启动消息。btw, 启动消息同时可以看成是热更新的重启消息。
无论是主干执行序还是其它消息的响应函数,它们都可以在里面调用一个叫 sleep 的函数。这其实就是用底层的 timer 回调实现的。调用的时候,当前执行序会被调度器挂起,直到 skynet 计量指定的时间长度后,重新从这个断点继续执行。
这样做,隐藏了 timer callback 的细节,隐藏了异步性。用户也很难主动的并发出多条并行的执行序来,可以减少系统复杂性。
热更新该怎样做呢?
我希望是在更更新时,收到热更新消息后,只是在系统里设置了一个标记。然后在主干代码中,合适的位置去检查这个标记位,体面的结束。这比较像 C 语言中处理中断信号的手法。比简单粗暴的杀掉注册的 timer 更为合理。
ps. 前两天碰到了服务相互依赖性的问题。需要主动在启动流程中提示,依赖哪个服务先启动。也就是有个服务启动管理器的服务,响应服务启动的消息,以及提供 RPC 调用,可以在一个服务启动后,返回成功信号。
Comments
异步RPC的确是考验人的事, 要是和signal /slot 机制结合起来会怎样?
Posted by: kevin | (19) June 9, 2013 02:51 PM
用coroutine隐藏回调,会造成用户不清楚程序执行流程,造成隐藏的bug
Posted by: k | (18) April 15, 2012 11:14 PM
博客不错 http://www.sinogol.com/前来支持~
Posted by: 返利网 | (17) April 6, 2012 05:48 PM
第一次留言
Posted by: 手机 | (16) April 6, 2012 05:46 PM
第一次留言
Posted by: Anonymous | (15) April 6, 2012 05:44 PM
建议看下libevent的实现。相当漂亮。你们要的异步IO和timer都可以参考。
Posted by: 浩毛 | (14) April 6, 2012 11:05 AM
看到p.s.,突然觉得你们在写一个OS了……和upstart很像……
Posted by: Liu LIu | (13) April 4, 2012 11:28 AM
“我们整个系统不应该存在任何显式的回调机制”
这是我的梦想啊
Posted by: mayao11 | (12) April 2, 2012 07:37 PM
好像不能完全解决异步带来的时序问题。==>用户也很难主动的并发出多条并行的执行序来,可以减少系统复杂性。
于QC而言,其实该做的检查和判断还是需要做的,写逻辑的人,防御式编程的思想还是要有的。
Posted by: 尘埃落定 | (11) April 1, 2012 05:27 PM
开源开源。- -#
Posted by: php | (10) April 1, 2012 02:38 PM
要是云风的大部分代码都开源了 我们就爽歪歪了
Posted by: crazy | (9) April 1, 2012 02:10 PM
timer 游戏频繁使用的, 看看云风怎么实现的
Posted by: crazy | (8) April 1, 2012 02:03 PM
你这这篇开发笔记描述的场景和我最近开发的业务很像。我们的平台是一个事件处理模式,可以实现同步和异步编程的效果,而且大量的使用了Timer。
前几天组内讨论时发现,业务结果的发放需要异步,即第三方请求过来,我们直接告诉他已开始处理,等业务处理好会回调第三方接口告诉它处理结果,这样就需要第三方请求时带一个id过来,处理完我们把id一同推回给他。
是不是和你们的场景很像??
Posted by: 方及道 | (7) March 31, 2012 10:56 PM
确实都异步事件。前半文有共鸣,后半文没来理解楼主的意思。
Posted by: zhaoyang | (6) March 31, 2012 08:43 PM
架构设计方面的东西太考验人了
Posted by: 老栋 | (5) March 31, 2012 07:38 PM
看不懂啊,风哥。
Posted by: ffffffffff | (4) March 31, 2012 04:29 PM
云风timer会用linux内核那套吗?挂接在数组上
Posted by: lin_style | (3) March 31, 2012 03:32 PM
热更新难道不是用lisp之类的更方便么?
Posted by: 过客 | (2) March 31, 2012 03:31 PM
坐回沙发吧。
支持一下,感觉你们才是在做hacker的事情啊,不像我们码农,哈哈
Posted by: egamesir | (1) March 31, 2012 03:30 PM