新的项目第一次采用skynet服务端框架做一个棋牌类的手游,客户端选型自quick-cocos2dx,双端都是lua,复用了斗地主的核心逻辑代码,很快就把大厅和打牌逻辑完成了,下面对skynet做了一个总述梳理。
skynet是一个多线程,基于actor的游戏服务器框架,它启动时开启固定线程,采取二级消息队列的分发。
它的C代码完成了skynet框架主要的任务,即消息分发和线程调度。在skynet框架里,skynet_context是可以被调度上线程的最小实体,每个逻辑服务实际上就是基于这个skynet_context上下文,它拥有一个私有消息队列,向一个服务发送一个消息就是把消息压入私有队列里。skynet维护一个全局队列,里面放了数个不为空的次级队列,工作线程不断从主消息队列里取出一个次级队列,再从一个次级队列里取出一条消息,调用对应服务的callback函数,用户定义的callback函数不必保证线程安全,因为在callback调用过程中,其他工作线程不可能得到这个服务的次级消息队列,也就不可能被并发。
在Lua层,我们可以方便地编写出skynet服务,这个服务可以处理其它服务发送过来或者直接底层网络接收到的消息,这样,我们的lua代码就可以运行在多线程的环境里面了。值得说明的是,每个lua服务其实都是彼此独立创建的一个Lua state,服务callback被调用时,消息压入Lua虚拟机中,skynet会为lua层的每个请求建立一个独立的coroutine,一旦这个coroutine中发生了skynet.call(即发送一个消息包),coroutine便挂起,在lua层会记录这个发送消息包的session和当前coroutine,callback正常返回,当下次带有该session的callback被调用时,coroutine被resume,lua代码完成一次rpc调用。
先总结到这里,祝大家使用顺利!