网关层设计与实现
概述
网关是游戏的"大门":所有客户端连接都在这里,负责接入、转发、防护。网关的核心职责是连接管理与流量转发,关键设计点包括:Netty/WebSocket 的接入、连接与玩家 ID 的全局映射、转发规则、以及灰度发布支持。本文设计完整的网关层。
一、接入网关设计
1.1 接入选型
接入方案:
Netty TCP:自定义协议(高效,棋牌类常用)
Netty WebSocket:浏览器/H5/小游戏(见网络层章节)
混合:TCP 与 WS 同时支持(同一逻辑)
网关边界:
连接建立/断开、心跳保活
协议编解码(复用自定义协议章节)
消息转发(不处理业务)// 网关启动(Netty TCP + WS 双协议示例)
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new GatewayInitializer()); // 编解码 + 转发 Handler1.2 网关无状态
网关不存业务状态:
玩家状态在逻辑层(分片)
网关只维护连接上下文(Channel、心跳状态)
网关可水平扩展(无状态)
连接上下文:
ConnectionContext:channelId、playerId(鉴权后绑定)
心跳计数、最后活跃时间
待转发队列二、连接与玩家 ID 映射
2.1 全局会话
映射两级:
本地:channelId → Channel(网关内存)
全局:playerId → 网关节点(Redis)
Redis Global Session:
key: online:{playerId} = { node, channelId, loginTime }
登录写入,下线/超时删除
用途:
跨网关定位玩家(私聊/好友通知)
同账号顶号(旧连接被踢)
在线状态统计登录绑定流程:
1. 客户端连任意网关节点
2. 登录鉴权(Token 校验,见账号章节)
3. 检查是否顶号(旧会话踢下线)
4. 写 Redis 全局会话
5. 通知逻辑层玩家上线2.2 路由与转发
消息转发路径:
客户端 → 网关(编解码)→ 查会话 → 转发逻辑节点
路由规则:
按 playerId 路由 → 玩家分片节点
按 roomId 路由 → 房间所在节点
全局服务(排行榜)→ 独立服务地址// 转发示例(网关 → 逻辑节点 RPC)
public void forward(PlayerMsg msg) {
String node = globalSession.lookup(msg.playerId);
NodeClient client = nodeClients.get(node);
client.send(msg); // 转发给逻辑节点
}2.3 回执与下行
下行链路:
逻辑节点 → 网关(RPC)→ 找到连接 → 写回
路径:
逻辑节点处理完 → 带 playerId 回执
网关按 playerId 查本地连接 → channel.writeAndFlush
玩家已切网关 → 查 Redis 会话 → 转发到新网关三、流量转发规则
3.1 消息分发策略
按消息类型路由:
玩家业务消息 → 玩家所在逻辑节点
房间消息 → 房间所在节点
系统广播 → 网关层直接广播(在线玩家)
规则表:
opcode → 路由策略(玩家/房间/全局)
配置化维护(新消息类型加配置)3.2 网关防护
网关前置防护:
限流:连接数限制、单连接频率限制(见聊天限流)
超时:空闲连接断开(IdleStateHandler)
协议校验:非法消息丢弃
防攻击:异常连接封禁(IP/设备)
目的:
业务层只处理合法请求
网关是第一道防线(见安全章节)四、灰度发布支持
4.1 灰度策略
灰度发布(新版本逐步放量):
按玩家比例:前 10% 玩家走新版本节点
按用户标签:白名单/渠道/新用户
按路由规则:特定消息走新逻辑
网关是灰度入口:
新逻辑节点上线 → 路由规则部分生效
回滚:改路由规则(立即切回旧节点)// 灰度路由示例
public String routePlayer(long playerId) {
if (grayService.isGray(playerId)) {
return GRAY_NODE; // 灰度玩家走新节点
}
return MAIN_NODE;
}4.2 灰度注意事项
灰度要点:
连接稳定(灰度玩家的长连接不受影响)
灰度期间新旧版本数据兼容
指标对比(错误率/延迟)决定放量或回滚
房间跨版本问题:灰度玩家不与旧版玩家同局(或兼容)优雅下线:
网关节点维护时 → 摘除负载均衡 → 存量连接给缓冲
通知玩家重连(或服务端踢出重连)
见运维章节(灰度发布/优雅关闭)五、实现要点
核心接口:
onConnect/onDisconnect // 连接生命周期
bindPlayer(channelId, playerId) // 鉴权后绑定
forwardToLogic(playerId, msg) // 上行转发
pushToPlayer(playerId, msg) // 下行推送
broadcast(msg) // 全服广播工程注意:
连接上下文线程安全(EventLoop 串行)
全局会话 TTL 与心跳联动(防僵尸会话)
转发超时与重试(逻辑节点不可达)
网关监控(连接数/QPS/转发延迟)常见坑:
连接与玩家映射丢失 → 会话绑定/解绑完整
顶号处理不干净 → 踢旧连接 + 清理会话
网关重启丢连接 → 客户端自动重连
转发黑洞 → 超时 + 告警与其他系统衔接:
编解码 → 自定义协议章节
心跳 → 会话管理章节
全局会话 → 水平扩展章节
灰度 → 运维章节