# xmgameservice **Repository Path**: xingbboy/xmgameservice ## Basic Information - **Project Name**: xmgameservice - **Description**: 魔兽争霸3 xm游戏服务 - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-19 - **Last Updated**: 2026-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 魔兽服务器 基于 Go 实现的多人游戏服务端,面向 Warcraft III 及类似游戏场景,负责处理客户端长连接、用户认证、游戏房间、地图房间、游戏消息、玩家数据、存档、排行榜、安全卫士和 Lua 游戏脚本等功能。 项目由三个独立服务组成: - **game-service**:面向游戏客户端,处理 WebSocket 连接、命令分发、在线用户、游戏房间、地图房间和实时消息,并提供系统指标和网关状态接口。 - **log-service**:面向后台数据处理,消费 Redis Stream 中的游戏事件和日志,并写入 PostgreSQL。 - **gateway**:分布式负载均衡网关,负责客户端接入认证、按房间路由到对应 game-service,并对 HTTP 管理接口做反向代理。 ## 功能概览 - WebSocket 长连接和客户端心跳 - 用户登录、重连、退出和在线状态管理 - 普通游戏房间和地图房间 - 房间广播、系统消息和批量命令 - 玩家数据读写、增量更新和周期重置 - 游戏存档保存、恢复和完整性校验 - 排行榜查询、玩家排名和排行数据更新 - Lua 脚本加载、编译、缓存和运行 - Lua 日志、错误日志和调用栈收集 - 安全卫士文件清单和未知文件上报 - Redis Stream 异步事件处理 - PostgreSQL 游戏数据、日志和统计持久化 - MongoDB 基础适配能力 - 网关接入认证、按房间路由和多游戏服负载均衡 - 游戏服系统指标采集(CPU、内存、磁盘、网络) - 网关健康检查和服务状态查询 ## 系统架构 ```text 游戏客户端 | | WebSocket /ws v +--------------------+ | gateway | |--------------------| | CDKey 接入认证 | | 登录首包解析 | | 房间路由(Redis) | | 负载均衡选择游戏服 | | HTTP 反向代理 | +--------------------+ | 重定向到 game-service v +--------------------+ | game-service | |--------------------| | 用户管理 | | 游戏房间 | | 地图房间 | | Lua 脚本运行时 | | HTTP 管理接口 | | 系统指标采集 | | 命令分发 | +--------------------+ | | | Redis | PostgreSQL v v +--------------------+ +----------------------+ | Redis Stream | | 游戏数据和日志数据库 | | game / log | +----------------------+ +--------------------+ ^ | +--------------------+ | log-service | |--------------------| | 游戏事件消费 | | 日志消费 | | 统计和排行榜 | | Lua 错误记录 | +--------------------+ ``` 主要数据流: 1. 客户端通过 WebSocket 连接 `gateway`,并通过 `Sec-WebSocket-Protocol` 提供 CDKey。 2. 网关校验 CDKey 对应的 AES 密钥,解密客户端首个 `login` 包,提取 `gameGuid`、`roomid` 和 `time` 组成路由键。 3. 网关按路由键查询或创建 Redis 房间路由(`gateway:room:*`),按负载评分选择健康的 game-service,并向客户端返回 `redirect` 重定向包。 4. 客户端携带重定向地址连接目标 `game-service`。 5. 服务端解码文本或二进制业务包,并交给命令组处理。 6. 用户、房间和地图房间状态在内存中实时维护。 7. 游戏事件写入 Redis Stream 的 `game` 流。 8. Lua 日志、Lua 错误和安全卫士日志写入 Redis Stream 的 `log` 流。 9. `log-service` 消费 Stream,并将数据写入 PostgreSQL。 10. HTTP 管理接口可向用户、游戏或房间广播消息,并提供存档、排行榜和安全卫士能力;经网关的 HTTP 请求会被反向代理到选中的 game-service。 ## 技术栈 - Go 1.24.1 - WebSocket:`github.com/gorilla/websocket` - Redis:`github.com/redis/go-redis/v9` - PostgreSQL:`github.com/lib/pq` - MongoDB:`go.mongodb.org/mongo-driver` - Lua:`github.com/yuin/gopher-lua` - 系统指标:`github.com/shirou/gopsutil/v4` - 配置:Viper、pflag - 日志:Zap - 压缩:zlib - 加密:AES-GCM - 部署:Docker、Docker Compose ## 项目结构 ```text . ├── cmd/ │ ├── game-service/ 游戏实时服务 │ │ ├── commands/ 客户端命令处理 │ │ ├── httpService/ HTTP 管理接口、系统指标和网关状态 │ │ ├── luaengine/ Lua 运行时和脚本管理 │ │ ├── roommanage/ 游戏房间和地图房间 │ │ ├── usermanage/ 在线用户管理 │ │ └── worker/ WebSocket 业务工作器 │ ├── gateway/ 负载均衡网关 │ │ ├── config/ 网关配置 │ │ ├── gatewaymanage/ 路由、健康检查和 WebSocket 接入 │ │ └── httpService/ 网关 HTTP 接口和反向代理 │ └── log-service/ 日志、统计和 Stream 消费服务 │ └── commands/ 日志事件处理 ├── internal/ │ ├── DB/ Redis、PostgreSQL、MongoDB 适配层 │ ├── cert/ HTTPS 自签名证书 │ ├── dataManage/ 线程安全动态数据管理 │ ├── encrypt/ 哈希工具 │ ├── http/ HTTP 和 WebSocket 基础设施 │ ├── logger/ 日志系统 │ ├── network/ 网络包编解码和加密 │ └── object/ 动态对象取值工具 ├── Dockerfile 多阶段构建文件 ├── docker-compose.yml 完整容器编排 ├── entrypoint.sh 容器启动脚本 ├── go.mod Go 模块和依赖 └── go.sum 依赖校验信息 ``` ## 服务说明 ### game-service 目录:`cmd/game-service` - 默认端口:`7777` - WebSocket:`/ws` - 健康检查:`/ping` - 处理登录、准备、退出、重连、保存、统计和房间操作 - 管理普通游戏房间、地图房间和在线用户 - 加载并运行 PostgreSQL 中的 Lua 脚本 - 提供游戏、房间、用户、存档、排行榜和安全卫士 HTTP 接口 - 每 10 秒采集一次系统指标(CPU、内存、磁盘、网络) - 将游戏行为和日志事件投递到 Redis Stream 主要 HTTP 接口包括: | 接口 | 作用 | | --- | --- | | `/ping` | 服务健康检查 | | `/GameMessage` | 向指定游戏或在线玩家发送消息 | | `/RoomMessage` | 向游戏房间或地图房间广播消息 | | `/UserMessage` | 向指定在线用户发送消息 | | `/ArchiveBackup` | 保存游戏存档 | | `/ArchiveRestore` | 恢复游戏存档 | | `/GetRankList` | 查询排行榜数据 | | `/UpdateSecurityGuard` | 处理安全卫士数据 | | `/gateway/status` | 返回连接数、房间数、玩家数和系统指标,供网关健康检查使用 | | `/gateway/rooms/{roomid}` | 查询指定房间是否存在及其状态 | ### log-service 目录:`cmd/log-service` - 默认端口:`7778` - 健康检查:`/ping` - 创建并消费 Redis Stream `game` 和 `log` - 记录房间创建、加入、离开和关闭事件 - 保存游戏统计、玩家数据和地图房间数据 - 保存 Lua 日志、Lua 错误和安全卫士日志 - 将异步事件持久化到 PostgreSQL ### gateway 目录:`cmd/gateway` - 默认端口:`7780` - WebSocket 接入:`/ws`,客户端通过 `Sec-WebSocket-Protocol` 提供 CDKey - 健康检查:`/ping` - 服务状态:`/status`,返回网关活跃连接数和各游戏服健康状态 - 使用 CDKey 对应的 AES 密钥解密客户端首个 `login` 包 - 以 `gameGuid:roomid:time` 为路由键,将同一房间固定路由到同一 game-service - 房间路由保存在 Redis(键前缀 `gateway:room:`),并按 `room_ttl` 自动过期 - 按玩家数、房间数、连接数、CPU、内存、磁盘和网络综合评分选择负载最低的游戏服 - 定时(默认 60 秒)拉取各游戏服 `/gateway/status` 健康状态 - 将其余 HTTP 请求反向代理到选中的 game-service 网关只负责接入和路由,客户端完成重定向后与 game-service 直接通信。 ## 环境要求 本地开发需要: - Go 1.24.1 或兼容版本 - Redis 6 或更高版本 - PostgreSQL 16 或兼容版本 - 可选:MongoDB - Docker 和 Docker Compose(容器部署时需要) ## 配置 ### 游戏服务 默认配置位于 `cmd/game-service/config.yaml`: ```yaml port: 7777 bind: "0.0.0.0" maxprocs: 4 redis: port: 6379 host: "127.0.0.1" password: "" db: 0 postgres: port: 5432 host: "127.0.0.1" user: "postgres" password: "" db: "pms_db" ``` ### 日志服务 默认配置位于 `cmd/log-service/config.yaml`,结构与游戏服务基本一致,默认端口为 `7778`。 ### 网关 默认配置位于 `cmd/gateway/config/gateway.yaml`: ```yaml bind: "0.0.0.0" port: 7780 room_ttl: "9h" redis: addr: "127.0.0.1:6379" password: "" db: 0 servers: - id: "game-1" health: "http://127.0.0.1:7777/gateway/status" addr: "ws://localhost:7777/ws" capacity: 1000 weight: 1 ``` `servers` 列表配置所有可用的 game-service:`health` 为健康检查地址,`addr` 为下发给客户端的 WebSocket 重定向地址,`capacity` 为最大玩家容量,`weight` 为负载权重。 ### 配置加载方式 配置加载支持 YAML、命令行参数和环境变量。所有服务均支持 `WAR3_` 前缀的环境变量覆盖,例如: | 环境变量 | 对应配置项 | | --- | --- | | `WAR3_POSTGRES_PASSWORD` | `postgres.password` | | `WAR3_REDIS_PASSWORD` | `redis.password` | | `WAR3_POSTGRES_HOST` | `postgres.host` | | `WAR3_REDIS_HOST` | `redis.host` | 容器环境中,服务通过命令行参数和 Docker Compose 注入的环境变量连接 `redis`、`postgres` 等容器服务名。不要在容器配置中使用 `127.0.0.1` 访问其他容器。 常用配置项: | 配置项 | 说明 | | --- | --- | | `port` | 服务监听端口,游戏服务默认 `7777`,日志服务默认 `7778`,网关默认 `7780` | | `bind` | 监听地址,`0.0.0.0` 表示监听所有网卡 | | `maxprocs` | Go 运行时最大使用的逻辑 CPU 数量 | | `fixed_iv` | AES-GCM 固定 IV 来源字符串,见下文"网络数据包" | | `redis.host` | Redis 地址 | | `redis.password` | Redis 密码 | | `postgres.host` | PostgreSQL 地址 | | `postgres.password` | PostgreSQL 密码 | | `room_ttl` | 网关房间路由有效期,默认 `9h` | 生产环境请替换配置中的空密码,并避免将包含真实凭据的 `config.yaml` 提交到仓库。 ## 本地运行 ### 下载依赖 ```bash go mod download ``` ### 启动基础服务 可以使用 Docker Compose 只启动 PostgreSQL 和 Redis: ```bash docker compose up -d postgres redis ``` 确认数据库和 Redis 可访问后,分别启动各服务。 ### 启动游戏服务 ```bash go run ./cmd/game-service ``` 启动后默认监听 `0.0.0.0:7777`。 ### 启动日志服务 打开另一个终端: ```bash go run ./cmd/log-service ``` 启动后默认监听 `0.0.0.0:7778`。 ### 启动网关(可选) 只有在需要多游戏服负载均衡时才需要网关: ```bash go run ./cmd/gateway -config cmd/gateway/config/gateway.yaml ``` 启动后默认监听 `0.0.0.0:7780`。 ### 构建二进制文件 ```bash go build -o game-service ./cmd/game-service go build -o log-service ./cmd/log-service go build -o gateway ./cmd/gateway ``` ## Docker 部署 Dockerfile 使用多阶段构建,同时编译 `game-service`、`log-service` 和 `gateway`,并将三个服务及各自默认配置打包到运行镜像中。 构建镜像: ```bash docker build -t w3service:latest . ``` 准备 `.env` 文件: ```dotenv POSTGRES_PASSWORD=change-this-postgres-password REDIS_PASSWORD=change-this-redis-password ``` 启动完整服务: ```bash docker compose up -d ``` 查看状态和日志: ```bash docker compose ps docker compose logs -f game docker compose logs -f log docker compose logs -f gateway ``` Compose 默认端口: | 服务 | 宿主机端口 | 用途 | | --- | ---: | --- | | PostgreSQL | `5432`(仅绑定本机) | 数据库 | | Redis | `6379`(仅绑定本机) | 缓存和 Stream | | game-service | `7777` | 游戏客户端和游戏接口 | | log-service | `7778` | 日志服务接口 | | gateway | `7780` | 客户端接入和 HTTP 代理 | `docker-compose.yml` 中还定义了 `game-2`、`game-3` 两个启用 `multi-game` profile 的游戏服,可使用 `docker compose --profile multi-game up -d` 启动多游戏服场景;同时在网关配置的 `servers` 列表中补充对应条目。 `docker-compose.yml` 中的 `backend` 和 `frontend` 服务属于配套管理后台项目。如果只部署本项目,可以按实际环境移除或停用这两个服务。 ## 网络数据包 二进制业务包的处理流程如下: ```text 业务数据 map[string]any -> JSON 编码 -> zlib 压缩 -> AES-GCM 加密(可选) -> WebSocket BinaryMessage ``` 配置项 `fixed_iv` 非空时使用固定 IV 兼容模式(向后兼容历史客户端);为空时生成随机 nonce,并将 nonce 放在密文前部,需客户端同步支持。数据包加密只保护通信内容,不替代 HTTP 管理接口的身份认证和权限校验。 ## Redis Stream 项目主要使用以下 Stream: - `game`:游戏房间、玩家行为、统计和玩家数据事件 - `log`:Lua 日志、Lua 错误和安全卫士相关日志 `game-service` 负责生产事件,`log-service` 负责消费并持久化。部署时需要确保两个服务连接同一个 Redis 实例和数据库编号。 网关使用同一 Redis 实例保存房间路由(键前缀 `gateway:room:`)和查询 CDKey 对应的 AES 密钥。 ## 日志和数据目录 - 日志模块基于 Zap,同时输出控制台和文件日志。 - 默认日志目录为可执行文件目录下的 `log/`。 - Docker Compose 将日志目录挂载到 `./log`。 - PostgreSQL 数据默认持久化到 `./postgres-data`。 - Redis AOF 数据默认持久化到 `./redis-data`。 上述目录通常包含运行时数据,不应提交到版本控制。 ## 安全注意事项 - 不要使用空 Redis 密码、空数据库密码或示例密码运行生产服务。 - `/GameMessage`、`/RoomMessage`、`/UserMessage` 等管理接口应部署在受控网络中,并通过网关或服务层补充鉴权。 - WebSocket 数据包加密不等于管理接口鉴权,二者需要分别配置。 - `fixed_iv`、AES 密钥、CDKey 和证书相关配置属于敏感信息,应通过安全配置中心或受保护的环境变量提供。 - 不要将日志、数据库目录、自动生成的证书和真实配置提交到仓库。 - 公开部署时只开放必要端口,Redis 和 PostgreSQL 不建议直接暴露到公网。 ## 相关项目 配套管理后台位于相邻的 `魔兽后台-公开版` 项目,包含 Java 后端和 Vue 前端,可通过 Docker Compose 与本项目的游戏服务、日志服务、PostgreSQL 和 Redis 组合部署。 ## 许可证 当前仓库未提供独立许可证文件。使用、修改和再发布前,请根据项目实际授权约定确认许可范围。