# Gate 节点说明 ## 节点定位 - 作为外部客户端的统一接入网关,维护长连接与心跳 - 负责登录鉴权、限速控制、协议白名单校验 - 根据会话中记录的节点信息,将请求路由到 Game / Map 等后端节点 - 维护玩家与网关连接的缓存,支持跨节点推送与踢人 ## 启动流程 - 入口:[gate.go](./gate.go) - 基于 Cherry 框架配置并启动节点: - ConfigureNode:以 Cluster 模式启动,开启网关特性(第二个参数为 true) - cherryApp.Init:初始化全局应用对象、加载配置 - 注册组件: - GOPS:运维诊断 - 配置中心:SDK、ProtoRoute、RateLimiter、Lua - Redis 客户端:GUID、Center - Rate 限速组件 - 注册 Actor:sessions.NewActor(false) - initApp:设置网关专用的网络解析器(UserActorParser) - Startup:启动网络监听与消息循环 ## 用户解析 Actor(UserActorParser) - 文件:[user/actor.go](./user/actor.go) - 角色:作为网关上的核心解析器,负责客户端数据流转、心跳、路由与节点同步。 - 初始化逻辑: - 在 OnInit 中注册远程接口: - User_PlayerPush:由后端节点向玩家推送消息 - User_PlayerKick:由后端节点控制玩家下线 - 初始化状态码:预先序列化“重复登录”“未登录”等错误码字节,便于快速踢线 - 初始化心跳:从配置读取网关心跳超时时间,注册 Heartbeat 包处理 - 初始化新连接回调:每个新连接创建一个子 Actor(actorAgent)负责该连接的会话与登录 - 注册数据包路由函数:OnDataRoute,用于处理客户端所有业务消息 - 初始化节点路由函数:为 Game / Map 等节点注册路由策略 - 初始化节点同步函数:在 Session 变更或连接关闭时同步到目标 Game / Map 节点 - 注册网络连接器:当前使用 TCP 监听 cherryApp.App().Address() ## 会话子 Actor(actorAgent) - 文件:[user/actor_agent.go](./user/actor_agent.go) - 角色:与单个 pomelo.Agent 一一对应,负责该连接上的登录流程、Session 设置、同步与关闭处理。 - 核心逻辑: - Login 流程: - 校验基础参数与 debug 模式下的 GameNodeID - validateToken:解析并校验登录 token(PID、OpenID、签名等) - 从 SDK 配置表中获取渠道信息,校验 PID 合法性 - 调用 Center 节点(CenterPlayer)根据 PID / OpenID 获取 UID - 调用 checkNodeState 确认目标 Game 节点可用(在线人数、维护状态、白名单等) - 通过 pomelo.Bind 将 UID 与当前会话绑定,如存在旧会话则踢出 - 在 Session 中记录 GameNodeID、PID、OpenID 等字段 - 返回 UserLoginResponse,包含 UID、PID、OpenID、GameNodeID 及扩展参数 - SetSession: - 根据传入的 StrStrList 动态设置 / 删除 Session 键值 - 调用 cache.UpdateAgent 刷新玩家在缓存中的映射 - 遍历需要同步的键,按 key 查找对应 SyncFunc(例如 game / map),推送 Session 到对应节点 - OnSessionClose: - 从缓存中移除 Agent - 调用所有 SyncFunc 执行解绑逻辑(包括 Redis 中的 session 数据) - 清理自身引用并退出 Actor ## 数据路由与限速 - OnDataRoute(user/actor.go) - 构建 Session 并打印调试日志(可选) - 协议路由白名单校验:使用 data.ProtoRoute 限制可访问的路由 - 限速控制:优先基于 UID,其次基于 IP 调用 rate.Check - 登录状态检查:未绑定 UID 且不是 GateUser_Login,则立即踢下线 - 本地路由:当当前节点类型与目标 route.NodeType 相同时,构造 ChildPath,通过 LocalDataRoute 将请求转发给本节点内部 Actor - 远端路由前的检查: - 再次确认 Session 已绑定 UID - 对除 GameLogin_Enter 外的路由,要求 Session 中已经存在 PlayerID - 节点路由:根据 NodeType(Game / Map)获取 routeFunc,完成真正的集群路由 ## 节点路由函数 - 文件:[user/route.go](./user/route.go) - Game 节点路由(gameNodeRoute): - 从 Session 中获取绑定的 GameNodeID,不存在则踢下线 - 通过 ClusterLocalDataRoute 将消息发送到对应 Game 节点 - Map 节点路由(mapNodeRoute): - 仅在角色已进入游戏(GameLogin_Enter)后才能访问 - 从 Session 中获取 MapNodeID,若为空则返回 NodeMapNodeIDIsEmpty - 使用服务发现(Discovery)检查目标 Map 节点是否存在,不存在则返回 NodeMapIsClosed - 否则通过 ClusterLocalDataRoute 转发消息 - 节点状态检查(checkNodeState): - 调用目标节点上的 Ops_CheckNodeState,用 UID 与 IP 进行校验 - 根据返回值或错误决定节点是否可进入,统一映射为 NodeIsClosed / NodeMapIsClosed 等错误码 ## 会话同步(Sessions Sync) - 文件:[user/sync.go](./user/sync.go) - sync2Game: - 从 Session 中取 GameNodeID 与 PlayerID - 当 isBind 为 true: - 将 Session 写入 Redis(SendRedisBind) - 向 Game 节点的 GateSessions Actor 发送 Sessions_Bind - 当 isBind 为 false: - 删除 Redis 中的 Session 映射(SendRedisUnbind) - 向 Game 节点发送 Sessions_Unbind(携带 PlayerID) - sync2Map: - 与 Game 类似,只是目标节点为 Map 节点,并不涉及 Redis 写入 ## 网关缓存(Agent Cache) - 文件:[cache/cache.go](./cache/cache.go) - 数据结构: - playerAgentsMap:playerID → Agent - gameAgentsMap:gameNodeID → {playerID → Agent} - mapAgentsMap:mapNodeID → {playerID → Agent} - UpdateAgent: - 根据 Session 中的 PlayerID / GameNodeID / MapNodeID 更新三张映射表 - 方便后续按玩家、按 Game 节点、按 Map 节点批量推送消息或踢人 - RemoveAgent: - 在连接关闭时,从上述三张映射表中删除对应记录 ## 推送与踢人 - playerPush(user/actor.go) - 支持按玩家、按 Game 节点、按 Map 节点三种模式推送: - Player:根据 I64List 中的 playerID 从 playerAgentsMap 中找到 Agent 逐个 Push - GameNode:根据 GameNodeID 找到对应 gameAgentsMap 后遍历 Push - MapNode:根据 MapNodeID 找到对应 mapAgentsMap 后遍历 Push - playerKick(user/actor.go) - 可按 FilterNodeIDS 过滤当前 Gate 节点 - 支持按玩家、按 Game 节点、按 UID、按 Map 节点踢人: - Player:从 playerAgentsMap 中查找并 Kick - GameNode/MapNode:按节点维度批量 Kick - UID:通过 pomelo.GetAgentWithUID 获取 Agent 后 Kick ## 典型调用流程 - 登录流程 - 客户端连接 Gate,网关创建 pomelo.Agent 与 actorAgent - 客户端发起登录请求(User_Login,本地路由到 actorAgent.login) - 网关校验 token、SDK 配置、获取 UID,检查 Game 节点状态 - 绑定 UID 与 Session,记录 GameNodeID / PID / OpenID - 向客户端返回 UserLoginResponse,同时通过 SetSession / Sync 将会话同步到 Game 节点 - 业务路由 - 客户端发送业务协议 - OnDataRoute 完成路由白名单、限速、登录状态检查 - 根据 Session 中记录的 GameNodeID / MapNodeID,将请求路由到对应节点 ## 设计目标 - 高吞吐:通过轻量级网关、会话分片 Actor 与缓存结构提升并发能力 - 安全性:统一的 token 验证、协议白名单、限速策略 - 一致性:通过 Redis + Sessions_Bind/Unbind 保证 Game 节点的会话感知与状态同步 - 可扩展性:节点路由、同步函数、缓存结构均可扩展新的节点类型或业务需求