基准 #
在本次评估中,我们对Nakama的部分工作负载进行了基准测试,测试对象为几个核心API,这些API通常用于构建大型多人游戏。
这些工作负载已经在一组不同的硬件配置上运行,以展示Nakama的对现代硬件友好且高可扩展的架构带来的性能优势。
结果表明:Nakama的性能随着硬件规模的增长而增长。向上和向外扩展都提供了许多优势:从集群管理的简化,到获得总体上更好的硬件和规模经济,均包括在内。
方法 #
基准测试用强大的分布式负载测试工具Tsung执行。
Tsung工作负载在单节点部署(Nakama OSS)和集群模式(NakamaEnterprise)中使用单个数据库实例,在几种不同的配置中对Nakama进行基准测试。
数据库实例硬件在所有配置和工作负载中保持不变,以确保没有I/O瓶颈。尽管我们还测试了一些数据库绑定的API,但这些基准测试将关注Nakama的功能。
Tsung服务器在Google Compute Engine (GCE)上运行。Nakama OSS和Enterprise均在我们的Heroic Cloud架构上运行。
在实际工作负载之前,并没有预热运行。
设置 #
Tsung / 数据库 #
Tsung拓扑结构由一个主节点和20个从节点组成。此设置在所有基准测试运行中都保持不变,硬件规格为:
Tsung Main | Tsung Redundant | 数据库 | |
---|---|---|---|
实例类型 | n1-standard-32 | n1-standard-32 | dedicated-core vCPU |
vCPU / Mem | 6 / 8GB | 3 / 2GB | 8 / 30GB |
IOPS (read/write) | - | - | 3000 |
数据库在Google CloudSQL上设定。
Nakama #
我们针对三种配置运行了基准工作负载:
Nakama OSS
- 1 节点 - 1 CPU / 3GB RAM
Nakama Enterprise
- 2 节点 - 1 CPU / 3GB RAM(每节点)
- 2 节点 - 2 CPU / 6GB RAM(每节点)
所有容器都在GCP实例类型“n1-standard-32”上运行,并在Heroic Cloud平台上创建。Nakama节点位于GCP L7负载平衡器后。
工作负载 #
建议的工作负载旨在显示针对轻松投产规模的Nakama的吞吐量和产能。
我们将展示以下工作负载的基准测试结果:
- 并存套接字连接数(CCU数)。
- 新用户注册吞吐量。
- 用户身份验证吞吐量。
- Lua运行时中自定义RPC吞吐量。
- Go运行时中自定义RPC吞吐量。
- 使用自定义比赛处理程序的权威实时比赛数。
以下小节分别针对上述每个工作负载,其中对每个工作负载都将进行更详细的介绍;然后是Tsung收集的每个考查的硬件和拓扑配置的基准结果。
结果 #
工作负载1 — 并发套接字连接数(CCU数)量 #
此工作负载包括验证用户、打开与Nakama的套接字连接,并保持其打开约200秒。
1 节点 - 1 CPU / 3GB RAM
连接的用户数
2 节点 - 1 CPU / 3GB RAM(每节点)
连接的用户数
2 节点 - 2 CPU / 6GB RAM(每节点)
连接的用户数
Hardware | Max Connected | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 19542 | 42.40 msec | 26.54 msec | 1340 / sec | 196.12 / sec | 34.21 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 27558 | 16.93 msec | 15.92 msec | 930 / sec | 161.52 / sec | 16.60 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 32092 | 20.17 msec | 18.18 msec | 1097.7 / sec | 187.82 / sec | 19.15 msec |
如上所示,具有单个CPU内核的单个Nakama实例可以有多达19500个连接用户。最多可扩展到2个节点,每个节点有2个CPU核,此值可达32000 CCU。
工作负载2 - 注册新用户 #
此工作负载模拟通过游戏服务器的设备身份验证API注册新用户,该API将新帐户存储到数据库中。
1 节点 - 1 CPU / 3GB RAM
吞吐量(请求/秒)
2 节点 - 1 CPU / 3GB RAM(每节点)
吞吐量(请求/秒)
2 节点 - 2 CPU / 6GB RAM(每节点)
吞吐量(请求/秒)
Hardware | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 29.07 msec | 20.10 msec | 849.6 / sec | 519.46 / sec | 24.60 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 31.65 msec | 20.01 msec | 1014.3 / sec | 672.18 / sec | 25.95 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 0.14 sec | 20.01 msec | 1160.8 / sec | 750.76 / sec | 28.46 msec |
如上所示,一台Nakama服务器可以处理平均约500个请求/秒的负载,在为新用户执行数据库写入操作时,请求以24.60毫秒(平均值)送达。按照这个速度,一个游戏每小时可以创建186万个新玩家。当扩展到2个节点时,该值将达到每小时270万个玩家账户。
工作负载3 — 对用户进行身份验证 #
此工作负载包括使用游戏服务器的设备身份验证API对现有用户进行身份验证。
1 节点 - 1 CPU / 3GB RAM
吞吐量(请求/秒)
2 节点 - 1 CPU / 3GB RAM(每节点)
吞吐量(请求/秒)
2 节点 - 2 CPU / 6GB RAM(每节点)
吞吐量(请求/秒)
Hardware | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 33.40 msec | 17.27 msec | 802.2 / sec | 499.63 / sec | 24.61 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 27.87 msec | 16.81 msec | 1035.5 / sec | 673.42 / sec | 22.19 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 76.85 msec | 16.95 msec | 1162 / sec | 776.77 / sec | 25.03 msec |
工作负载4 - 自定义Lua RPC调用 #
此工作负载执行通过Lua运行时公开的简单RPC函数。该函数接收JSON字符串形式的有效负载,对其进行解码,并将其回传给发送方。
1 节点 - 1 CPU / 3GB RAM
吞吐量(请求/秒)
2 节点 - 1 CPU / 3GB RAM(每节点)
吞吐量(请求/秒)
2 节点 - 2 CPU / 6GB RAM(每节点)
吞吐量(请求/秒)
Hardware | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 26.18 msec | 15.01 msec | 976.5 / sec | 633.42 / sec | 20.22 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 19.25 msec | 15.68 msec | 1192 / sec | 706.71 / sec | 17.48 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 20.27 msec | 16.11 msec | 1383.4 / sec | 823.55 / sec | 18.16 msec |
工作负载5 - 自定义Go RPC调用 #
此工作负载执行通过Go运行时公开的简单RPC函数。该函数接收JSON字符串形式的有效负载,对其进行解码并将其回传给发送方。
1 节点 - 1 CPU / 3GB RAM
吞吐量(请求/秒)
2 节点 - 1 CPU / 3GB RAM(每节点)
吞吐量(请求/秒)
2 节点 - 2 CPU / 6GB RAM(每节点)
吞吐量(请求/秒)
Hardware | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 26.12 msec | 14.42 msec | 975.9 / sec | 635.36 / sec | 19.97 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 20.87 msec | 14.91 msec | 1205.7 / sec | 707.12 / sec | 17.29 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 20.19 msec | 15.59 msec | 1386.4 / sec | 820.41 / sec | 18.00 msec |
如上所示,一台Nakama服务器平均可以在19.97毫秒(平均)内处理约600个请求/秒。当与工作负载5的结果进行比较时,我们发现Lua和Go运行时之间的结果非常相似。这是因为被基准测试的工作负载不会引起大量的CPU计算;使得尽管Lua虚拟机存在差异,结果仍然相似。对于CPU密集型代码,性能结果将有所不同,Lua运行时的RAM使用情况也会不同。
工作负载6 - 自定义权威比赛逻辑 #
此工作负载模拟在Nakama的服务器权威多人游戏引擎上运行的实时多人游戏。尽管客户端和自定义逻辑不是实际的多人游戏;从服务器和连接的游戏客户端之间交换的消息的角度,该代码创建了近似的真实用例场景。我们将简单介绍此工作负载中的服务器和客户端逻辑。
服务器端逻辑 #
服务器以每秒10次节拍率运行多人比赛。每场比赛最多可有10个玩家。
服务器实现了一个RPC调用,客户端可以查询该调用以获得正在进行的比赛(少于10名玩家)的ID。当调用此API时,服务器将使用列出比赛功能查找未满的比赛并返回第一个结果。如未找到比赛,则开始一个新的比赛。
比赛循环逻辑很简单;服务器期望从客户端接收两个操作码中的一个,并执行以下任一操作:
- 将收到的消息回显给客户端。
- 将消息广播给所有的比赛参与者。
客户端逻辑 #
客户端逻辑也很简单;每个游戏客户端按顺序执行以下步骤:
- 对现有用户进行Nakama身份验证以接收令牌。
- 执行服务器RPC函数以接收正在进行的比赛(未满)的ID。
- 建立与实时API的网络套接字连接。
- 使用步骤2中收到的ID加入比赛。
- 客户端将循环180秒,每半秒将交替发送一条操作码为1或2的消息。
客户端发送的消息包含固定大小的有效负载,操作码1和2分别为44和35个字符。
1 节点 - 1 CPU / 3GB RAM
连接的用户数
2 节点 - 1 CPU / 3GB RAM(每节点)
连接的用户数
2 节点 - 2 CPU / 6GB RAM(每节点)
连接的用户数
这些结果是客户端发出的每个请求的平均值,因为此工作负载涉及:
- 身份验证
- RPC调用
- 连接到网络套接字和
- 通过网络套接字连接发送消息;
结果考虑了在每个客户端会话中执行的整个请求逻辑集。
Hardware | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean |
---|---|---|---|---|---|
1 Node - 1 CPU / 3GB RAM | 42.21 msec | 1.07 msec | 126.5 / sec | 36.72 / sec | 15.06 msec |
2 Nodes - 1 CPU / 3GB RAM (each) | 0.10 sec | 1.14 msec | 213.8 / sec | 54.68 / sec | 28.21 msec |
2 Nodes - 2 CPU / 6GB RAM (each) | 41.82 msec | 1.07 msec | 350 / sec | 85.82 / sec | 15.93 msec |
下表包括游戏服务器利用比赛中交换的数据消息处理的网络吞吐量。可见,客户端接收的字节数远高于发送的字节数;如上所述,客户端发送的50%的消息由服务器广播给所有比赛参与者。
Hardware | Sent/Received | Highest Rate | Total |
---|---|---|---|
1 Node - 1 CPU / 3GB RAM | Sent | 4.65 Mbits/sec | 157.92 MB |
Received | 24.88 Mbits/sec | 809.65 MB | |
2 Node - 1 CPU / 3GB RAM (each) | Sent | 5.90 Mbits/sec | 201.35 MB |
Received | 31.96 Mbits/sec | 1020.68 MB | |
2 Node - 2 CPU / 6GB RAM (each) | Sent | 7.64 Mbits/sec | 261.61 MB |
Received | 40.54 Mbits/sec | 1.30 GB |