引言
这段时间,我结合 AI 对 MUD 的底层架构进行了一次深入的“手术”。
众所周知,FluffOS 传统的单线程架构将网络 IO、游戏逻辑、数据计算全部挤在同一个线程里。一旦在线玩家增多或遭遇攻击,卡顿(Lag)几乎成为必然。
为了彻底解决这个根源性问题,我设计了一套基于 Go 语言中间层(Gateway) 的解决方案。
核心思路简单而直接:“IO 与逻辑分离”。
目前这套架构已经跑通,并在内网压测中取得了令人振奋的数据。在此分享设计思路,欢迎各位同行交流指正。
说明:网关层可以用 Python、Node.js 等实现,选择 Go 是因其在该场景下的综合优势更突出。熟悉何种语言,便可选用何种语言实现。
最重要的一点:该架构对现有游戏代码完全零入侵,即可平滑升级。
架构全景:从直连到“旁路”部署
我们彻底改变了客户端直连 FluffOS 的传统模式,转而引入 Go 作为前置网关,并以 Sidecar(边车)模式 进行部署。
核心流程如下:
- 客户端层
支持 WebSocket、Telnet、HTTP 等多种协议接入,对玩家完全透明。 - Go Gateway
持有所有物理 TCP/WebSocket 连接。负责协议解析、粘包处理、加密(TLS)、压缩及流量清洗。 - TCP 单通道
这是关键设计。无论前端连接数有多少,网关与 FluffOS 驱动之间仅维护 一条 高速 TCP 长连接,实现 单通道多路复用(Single Channel Multiplexing)。 - FluffOS 驱动层
接收经网关清洗、序列化后的 MsgPack 二进制流,将其映射为虚拟玩家对象(Virtual User),从而专注于执行纯粹的 LPC 游戏逻辑。
架构示意图

二、 设计动机:我们解决了哪些痛点?
结合实际开发中的深刻体验,这套架构主要从四个维度带来了根本性提升:
1. 极致性能:单通道多路复用
- 痛点
传统模式下,1000 名在线玩家即消耗驱动层 1000 个文件描述符(FD)。每一次握手、断开、网络波动都会触发系统调用,频繁惊扰 FluffOS 单线程。 - 方案
通过 Go 网关进行连接聚合与多路复用,FluffOS 底层仅感知一个虚拟 FD。 - 收益
极大减少了操作系统的上下文切换开销。Go 网关利用其高效的 Goroutine 模型承担了全部网络 IO 压力。
压测数据:向内网虚拟 FD 发送 100 万个数据包,实测 QPS 达到 68万 ~ 86万,处理延迟保持在微秒级。彻底告别了“因 IO 阻塞导致的全服心跳卡顿”。
2. 协议归一化:高效的 MsgPack 传输
- 痛点
LPC 中字符串拼接效率低下,原生 Socket 通信常受 TCP 粘包问题困扰,业务代码中充斥着繁琐而脆弱的协议解析逻辑。 - 方案
网关内部集成统一的 WS Handler 与 Telnet Handler,将所有外来数据转换为带 Length Header 的 MsgPack 二进制流。 - 收益
LPC 层接收到的永远是结构化的数据包(Mapping/Array)。不仅传输体积更小(通常减少 30%-50%),而且从根源上解决了粘包问题。LPC 虚拟机无需再消耗宝贵的eval_cost进行复杂的字符串解析。
3. 虚拟连接技术:安全加固与会话保持
- 痛点
网络层与游戏逻辑层紧耦合,驱动进程若崩溃则全体玩家断线;且驱动直接暴露于公网,极易遭受各类网络攻击。 - 方案
在驱动层实现 “虚拟连接” 。LPC 中的玩家对象interactive_t其fd被标记为-1,成为一个纯粹的虚拟对象。 - 收益
- 攻击隔离:前端的 CC 攻击、端口扫描等恶意流量被 Go 网关全数拦截,脏数据根本无法触及 FluffOS。
- 无感重连与热重启:玩家物理连接的闪断由 Go 网关托管和自动重连。更进一步,当 FluffOS 驱动因更新或故障重启时,网关依然保持与所有玩家的连接。驱动恢复后,网关重新同步会话状态,实现真正的 “热重启不掉线”。
4. 零侵入开发:存量代码的完美兼容
- 痛点
底层架构升级往往意味着业务代码的重写或大规模适配,成本高昂。 - 方案
通过 Hook 底层驱动逻辑,在 LPC 层完整保持了master.c->connect()->login.c的经典调用链。同时,通过透传gateway_session_id与gateway_real_ip等元数据,业务逻辑层依然可以像过去一样获取玩家真实 IP。 - 收益
积累了十数年的现有 MUD 业务代码(凝聚了无数巫师心血),几乎无需任何修改,即可无缝迁移至这套高性能架构上运行。
三、 开发体验的变革:UI 与逻辑的清晰分离
除了底层性能的飞跃,这套架构也极大地解放了 LPC 开发者的生产力,尤其在 UI 交互层面:
- 过去的 UI 开发
不得不在 LPC 中痛苦地拼接ZJMENUF指令、ANSI 颜色码、换行符,代码臃肿且极难维护。 - 现在的 UI 开发
LPC 只需专注于生产和发送纯业务数据(结构化的 Mapping),由 Go 网关根据客户端类型(Telnet/Web/App)负责将其 “渲染” 成对应的终端协议。
// 如今的 LPC 代码示例:只关注业务逻辑,不关心表现层细节
me->send_ui(([
"title": "系统提示",
"content": "确认购买吗?",
"btns": ({
(["name": "确认", "cmd": "ok"]),
(["name": "取消", "cmd": "cancel"])
})
]));
四、 结语与展望
目前,该架构已完成核心通信、协议编解码及基础 LPC 适配,并修复了包括 Nonce 重用、UAF(释放后使用)在内的多个底层安全隐患。
在我看来,MUD 绝非应被尘封的“老古董”。通过引入 Go 等现代技术栈,实现 “Go 网关(高性能IO) + FluffOS(专注逻辑计算)” 的存算分离架构,我们完全有能力让经典的 FluffOS 引擎焕发新生,使其承载能力媲美现代网络游戏。
此番分享,旨在抛砖引玉。不知各位对这种架构模式有何见解?在实际运营中,您又遇到过哪些 FluffOS 的性能瓶颈?欢迎在评论区畅所欲言,共同探讨。
(若对代码实现细节感兴趣,也欢迎私信交流。)
MUD 不死,它只是在持续进化。