内容纲要

skynet 提供一个 gateserver 用于处理网络事件,位于 lualib/snax/gateserver.lua。云风在 skynet wiki 上介绍了 gateserver 的功能和使用范例。用户可以通过向 gateserver 提供一个自定义 handle 来向 gateserver 注册事件处理 (玩家登录,断开,数据到达等)。

gateserver 模块使用 C 编写的 socketdriver 和 netpack 模块,gateserver 被加载时,会注册对”socket”(PTYPE_SOCKET) 类型消息的处理,并且通过 netpack.filter 对收到的数据进行分包。分包完成后调用传入的 handler 对应的处理函数进行处理。它替上层使用者,完成对 PTYPE_SOCKET 消息的注册分发,以及消息分包。这样在使用时,只需提供一个 handler,然后调用 gateserver.start(handler) 即可。

在 skynet 中,如果你要自定义你的 gate 网关服务 gate.lua,需要执行以下几步:

  1. gateserver = require snax.gateserver
  2. gateserver.start(handler)向 gateserver 注册网络事件处理。
  3. skynet.call(gate, "lua", "open", conf)在外部向你定义的 gate 服务发送启动消息,并传入启动配置 (端口,最大连接数等) 来启动 gate 服务。

skynet 中也提供了一个 gate 服务,位于 skynet/service/gate.lua,作为使用 gateserver 的一个范例。gate 服务由 watchdog 启动,gate 服务维护外部连接状态,并且转发收到的数据包。skynet 提供的 gate 服务使用 agent 模式,关于 gate 服务的工作模式,在 skynet 设计综述中有段介绍:

Gate 会接受外部连接,并把连接相关信息转发给另一个服务去处理。它自己不做数据处理是因为我们需要保持 gate 实现的简洁高效。C 语言足以胜任这项工作。而包处理工作则和业务逻辑精密相关,我们可以用 Lua 完成。

外部信息分两类,一类是连接本身的接入和断开消息,另一类是连接上的数据包。一开始,Gate 无条件转发这两类消息到同一个处理服务。但对于连接数据包,添加一个包头无疑有性能上的开销。所以 Gate 还接收另一种工作模式:把每个不同连接上的数据包转发给不同的独立服务上。每个独立服务处理单一连接上的数据包。

或者,我们也可以选择把不同连接上的数据包从控制信息包(建立 / 断开连接)中分离开,但不区分不同连接而转发给同一数据处理服务(对数据来源不敏感,只对数据内容敏感的场合)

这三种模式,我分别称为 watchdog 模式,由 gate 加上包头,同时处理控制信息和数据信息的所有数据;agent 模式,让每个 agent 处理独立连接;以及 broker 模式,由一个 broker 服务处理不同连接上的所有数据包。无论是哪种模式,控制信息都是交给 watchdog 去处理的,而数据包如果不发给 watchdog 而是发送给 agent 或 broker 的话,则不会有额外的数据头(也减少了数据拷贝)。识别这些包是从外部发送进来的方法是检查消息包的类型是否为 PTYPE_CLIENT 。当然,你也可以自己定制消息类型让 gate 通知你

skynet 中提供的 gate 服务使用的 agent 模式,意味着,一开始,gate 将新连接的连接控制信息转发给 watchdog,如收到用户连接消息后,watchdog 可以完成一些登录验证等,验证完成之后,由 watchdog 创建并启动 agent 服务,agent 服务启动之后,会立即向 gate 服务发送一条”foward” 消息,表示” 现在玩家已经登录完成,你收到的消息可以交给我了”。gate 收到”forward” 消息会记录 agent 地址,并将之后玩家的数据消息转发给 agent 而不是之前 watchdog。gate 将消息转发给 agent 时,会通过 skynet.redirect 将源地址改为玩家地址,方便业务处理。

发表评论

电子邮件地址不会被公开。 必填项已用*标注