Skip to content
sniper00 edited this page Mar 1, 2019 · 29 revisions

简介

moon是一个轻量级的游戏服务器框架,专注于游戏开发。框架本身没有游戏业务层逻辑,主要目标是提供用于编写业务逻辑的基础功能。

源码目录

  • common 框架公共源码目录
  • lualib-src lua C Module 源码目录
  • moon 框架源码目录
  • third 第三方库目录
  • example 可执行文件工作目录,编译过后可执行文件会复制到这个目录
  • example/clib lua C Module目录,会自动添加到lua的搜索路径中
  • example/lualib 框架的lua层封装,会自动添加到lua的搜索路径中
  • example/service 框架提供的常用服务

框架设计

在传统的游戏服务器设计中,通常采用分模块-多进程模式,不同模块负责不同的功能。这样的好处是可以方便分布式部署,弥补单台机器的处理能力不足,并且一个进程故障不会让整个服务挂掉。但要让这些分散(位于同一台物理机,或者不同物理机)的进程作为一个整体服务,就要处理进程间的通信。要满足跨机器通信一般采用TCP,这样一个进程就要具备ListenConnect的能力,如果一个进程要处理客户端链接,还需要同时Listen两个端口。这样就需要维护多个网络连接,处理网络的各种异常情况,为了网络不影响逻辑,通常还会为网络开单独的处理线程,这样的设计不管是编码还是维护都比较复杂。

moon的设计目的就是把不同的功能模块集成的同一个进程当中,不再需要维护复杂的网络连接,比较强调单机处理能力,随着单机硬件性能提升,手游兴起,单机部署也能满足大多数情况。moon是按服务来划分的,一个服务可以代表一个模块,服务间的通信只是传递一个数据指针,比进程间通过IO通信高效的多。一个进程中的所有服务是同生共死的,服务间通信不必时刻关心对方是否还活着,通讯数据能否正确到达等问题。并且同时也具有多进程模式的优点:分布式部署cluster 提供了进程间服务通信的支持,用法上与进程内服务间通信几乎没有差异。可靠性:服务一般采用lua编写,这就提供了运行沙盒,防止某个服务crash而影响其他服务。对于使用lua编写的服务,采用lua协程来包装异步操作,使编写异步逻辑更加清晰简单。对于性能要求较高的场合,可以采用C++编写模块供lua调用。

网络

moon是以服务来处理具体业务的,默认情况下服务是不具有网络功能的,我们可以给服务添加网络组件。网络组件暂时只tcp协议。网络数据会传递给当前所在的服务进行处理,通过消息类型来区分网络消息和服务间通信的消息。对于收到的网络数据,消息的发送者就是网络连接的sessionid, 逻辑层可以通过这个id和客户端进行通信。

现在支持三种模式:

  • 2字节大端来表示数据长度的协议,这个是默认模式。这个数据长度不包含表示长度的2字节数据
  • websocket ,现在只支持服务端
  • 自定义解析,框架自带的redis客户端就是用的这种模式

客户端端想和服务器通信,只需要遵循这个分包协议,可以编写C/C++,C# ,lua,python等客户端。数据内容的格式可以自定义,如google protocol buffers 或者 json,或者自定义的协议。

消息

框架消息处理流程图

image

每条消息有:发送者服务id、接收者服务id、消息头、消息数据、responseid、消息类型 组成。

消息的数据分为 消息头和数据,这样做可以对游戏逻辑中的广播进行优化,例如 场景内某个玩家释放了技能,需要对周围玩家广播,对于周围玩家来说这是同一份数据,但对服务器来说数据是:接收者uid+玩家释放技能数据,通过网关服务广播给多个客户端,由于接收者uid是不同的客户端,这样就需要对数据重新进行组装,产生额外的数据拷贝。为了避免这种情况,我们可以把接收者id储存在消息头中,把技能数据存在消息数据中,这样网关服务只用检查消息头的接收者id,就可以把同一份数据发送给多个玩家。消息数据部分采用了引用计数的智能指针存储,使用完后会自动释放。

responseid 是用于请求回应模式,方便处理不同服务间通信。有时我们发送一条消息,并希望得到消息的处理结果:发送消息时附带一个responseid,并绑定一个lua协程,对方收到后把responseid发送回来,触发协程resume。

Clone this wiki locally