一个大型 MC 服务器架构思路
简介
早期的 Minecraft 服务器,是一个单体服服务器的结构,由于服务器程序运行在一个进程上,服务器的事件循环都是在服务器主线程(ServerThread)上计算,例如 AI、区块刻、物理计算、客户端通信等等,几乎都是在一个线程上处理的,随着玩家数量增多,加载的区块数量和实体就会变多,而单线程的处理性能是有限的,只能充分利用到 CPU 的一个核心,当单服性能达到瓶颈的时候,就会造成卡顿,每个游戏刻的运行时间将超过 50ms,严重影响玩家的游戏体验。
而像 Hypixel 那样可以承载几万人在线的服务器又是怎么样实现的呢,本文将会给出答案。
单服
简介里已经描述了,早期的多人游戏,是直接将游戏客户端与游戏服务器进行连接,如下图所示:
单服模型适合人数小于 100 人的服务器,在 1.12 版本以下可以容纳更多,在此模型里,所有的玩家都是在一个游戏服务器进程中。
客户端与服务器会话的建立与断开的过程比较复杂,进入到一个游戏服务器会涉及到以下几个数据包,按发送顺序从上往下排列,其中 Clientbound 代表服务器向客户端发送的消息,由客户端处理,Serverbound 则反之。
在一个完整的连接过程中,客户端和服务端的会话都会经历三个阶段,按顺序为 HANDSHAKING,LOGIN,GAMEPLAY,都是通过发送以上这几个数据包来通知对方到达了哪个阶段,并且到达了下一个阶段后是不能倒退到上个阶段的。
MC 代理服务器
若服务器想容纳更多人数,则需要开启多个 MC 服务器,让玩家在不同服务器上进行游戏,以达到负载均衡的目的,让玩家能够在不同服务器之间跳转而不用断开游戏连接,就需要用到 MC 服务器代理,目前市面上比较流行的代理服务器有 Bungee、Velocity 这两款。
使用一个代理服务器能很容易提升服务器的人数上限,承载个 1000 人没有太大问题,本文不讨论 MC 代理服务器的具体使用细节,而是聊聊其工作原理。一个简单的服务器集群的架构图如下:
在此模型中,客户端不直接与游戏服务器建立连接,而是先与 MC 代理服务器建立连接,代理服务器上记录了所有的游戏服务器的 IP 和端口信息,并且代理并不单纯负责数据包的转发,还承担了模拟服务器和客户端的功能。
每当代理服务器上新增一个新的客户端连接时,此连接称为上游 (Upstream),代理服务器上实现了一部分 MC 的通信协议,此时代理服充当服务端的功能,与客户端进行通信,在给客户端发送 GameProfile 的数据包后,客户端进入到 GAMEPLAY 阶段。
随后,代理服会与其中一个游戏服务器建立一个新的连接,此连接称为下游 (Downstream),将从客户端获取到的数据与游戏服务器进行通信,此时代理服务器充当客户端的功能,直到与游戏服务器的连接阶段进入到 GAMPLAY 阶段,之后会将上下游进行对接,上游收到的数据包转发给下游,下游收到的转发给上游,充当一个桥梁的作用。
之后便可以使玩家在不同的游戏服务器间进行切换,切换到下一个游戏服务器时,代理服务器都会重复上面这一步操作,将上下游无缝对接之后,断开玩家之前的下游服务器连接。
这就是 MC 代理服务器的主要工作原理,充当一个中间人的角色,使玩家能够在不掉线的情况下切换服务器,并具备 MC 的通信协议,还能够对数据包进行修改的操作,上下游的一部分数据包其实是不能直接进行转发的,仍然需要经过比较复杂的处理,例如实体ID映射表之类的,本文不多做描述了。
HAProxy 代理
单个 MC 代理服务器仍然还是会达到性能瓶颈,因为其并不单纯负责转发,还具有翻译的角色,上文提到过了,当服务器的人数达到千人级别时候,就需要对 MC 代理服务器进行一层负载均衡了。
Minecraft 使用 TCP 协议进行通信,常用的代理工具有 Haproxy,可以将客户端连接负载均衡到不同的 MC 代理服务器上,提供了几种常用的负载均衡策略,如轮训、最少连接数、随机、源IP等,架构图如下:
此时 MC 代理服务器也变成了一个集群,只需要将一个代理服务器复制几份,修改端口号或者在不同的机器上部署,其他的配置几乎相同,若是在不同的服务器上部署则需要注意配置文件下的游戏服务器IP信息,然后在 HAProxy 上配置好负载均衡策略。
DNS 域名解析
由于 HAProxy 也只是一个应用程序,若这一层也达到了性能瓶颈,出现了 CPU 跑满了的情况,就需要对 HAProxy 进行一层负载均衡。
此时可以使用使用 DNS 域名解析,玩家必须以域名的形式,而不是 IP 直接连接,每次访问域名时,都会得到不同的 IP 地址,以达到负载均衡的效果,HAProxy 也需要部署到不同的服务器上,并且要具备独立的公网IP,架构图如下:
此模型下,遇到了性能瓶颈就只需要拓展那一层的服务器程序,修改配置即可,理论上可以无限拓展,使服务器达到万人级别的规模。
以上便是 Hypixel 这类服务器能承载海量人数使用的架构,是通过层层代理实现的负载均衡,一般来说层数不会超过三层,层数太多造成的延迟问题也不小,实际上最后这个模型也就使用了两层代理,不会产生太大影响。