本文通过使用 MixBytes.Tank 和 Tank.bench 工具对 Polkadot 区块链的多个版本进行了深入测试。
作者:Sergey Govyazin
区块链开发者
前言
测试往往被忽视或搁置。在 MixBytes,我们认为开发不必是唯一的优先事项。
借助 MixBytes Tank - 我们用于复杂测试和基准测试的工具 - 我们决定挑战几个区块链项目,Polkadot 是这一系列的第一个。在它发布的众多版本中,我们选择了三个,版本 0.6.18 展现了最佳结果。*
最重要的是,网络经受住了我们施加的重负载攻击,其他细节在下面的综合报告中显示。系好安全带!
报告中提到的日志片段、图表截图和测试用例可以在 这里 找到。
MixBytes.Tank 和 Tank.bench
MixBytes.Tank 是一个易于配置的工具,用于快速简单地部署区块链网络。只需一条命令,即可以所需参数(如节点数量、验证者数量、计算机计算能力等)启动不同的区块链网络。
Tank.bench 是一个用于为区块链创建多样化负载的工具,主要通过交易生成。它集成在 Mixbytes.Tank 中。要加载使用 MixBytes.Tank 部署的集群,只需运行一条命令。
为了使这些工具能够与特定的区块链一起工作,需要编写相应的绑定,也就是说,特定于某个区块链的代码。Tank 需要一个用于部署 Polkadot 节点的指令,而 bench 需要创建交易并将其发送到网络的代码。
为了进行后续性能测量和故障排除,MixBytes 团队开发了两种工具:Polkadot bindingfor MixBytes.Tank 和 Polkadot binding for Tank.bench。
综合代码存放在以下代码库中:
https://github.com/mixbytes/tank
https://github.com/mixbytes/tank.ansible-polkadot
https://github.com/mixbytes/tank.bench-polkadot
使用 MixBytes.Tank 和 Tank.bench 的合成负载下的 Polkadot。研究结果
为 Polkadot 研究编写了相应的 Tank.bench 绑定和两个配置文件。其中一个通过转账交易加载区块链,另一个“抵押”资金。
关闭 OnlyStakingAndClaims 插件的 Polkadot v.0.6.18 进行转账交易进行了测试。
每个测试均使用特定的 Tank 和 bench 配置进行。配置详细信息在各自的代码库中描述。
测试使用 Google Cloud Engine 和 DigitalOcean 云服务提供商的机器进行。
大 机器配置:
Ubuntu 18.04.3 (LTS) x64; 磁盘 = 80GB; 内存 = 8192MB; VCpu = 4;
对于少于 60 台机器的测试,日志完全显示,而对于机器数量较多的测试,日志仅显示每个机器日志的最后 100 行。
在测试期间,Polkadot 发布了几个新版本。为了查明在之前基准测试中发现的问题是否已解决,对新版本 0.6.18 进行了测试。
Tank.bench-polkadot 已更新,因为之前用于测试 Polkadot 0.6.2 的版本失败。在更新依赖关系后,负载模块恢复了工作。以下是我们测试的一些结果。
测试 1:21 个验证者,本地化集群,稳定连接
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
count: 20
type: large
Tank.bench-polkadot
1,2) tps: 20, total-tx: 1000
profile: transfer
3) tps: 200, total-tx: 10000
profile: transfer
4) tps: 400, total-tx: 100000
profile: transfer
描述
该测试检查了具有 21 个验证者的网络的行为。如果没有错误发生,则可以执行负载测试。
在这里和后续,Tank.bench-polkadot 工具的 TPS 参数并不意味着区块链能够以此速度处理所有交易。该参数仅显示将交易添加到内存池的强度程度。
附加的数据交易加入到区块中可以在图表“过去 2 分钟的外部操作”中找到。
图表
结果
网络在 10 分钟内部署完成并工作了约 50 分钟,然后测试停止。进行了四个转账交易形式的负载会话。
显然,网络在负载测试启动之间处于稳定状态,节点 CPU 使用量不超过 10%。
所有负载测试显示几乎相同的结果:第一个交易立即添加到区块中,区块迅速完成。在某些时刻,交易开始转入内存池,并不情愿地进入区块。经过一段时间,内存池被清除。
在所有负载测试的日志中,负载工具显示某些交易抛出异常:
RPC-CORE: submitExtrinsic(extrinsic: Extrinsic): Hash:: 1010: Invalid Transaction: Stale
因此,这些交易无法到达验证者。
网络的稳定性远高于之前实验系列。验证者不再因不明异常而断开连接。区块调度没有延误,验证者几乎没有错过最终确认。包括不同数量交易充塞交易池而未进入区块的问题仍然存在。
日志
该测试的日志片段在以下文件中给出:
1_1.log(在网络启动前)
1_2.log(在负载测试 1 启动前)
1_3.log(在负载测试 2 启动前)
1_4.log(在负载测试 3 启动前)
1_5.log(在负载测试 4 启动前)
1_6.log(在网络停止前,在负载测试 5 启动后)。
测试 2:49 个验证者,本地化集群,稳定连接
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
count: 48
type: large
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 400, total-tx: 100000
profile: transfer
描述
该测试检查了具有 49 个验证者的网络的行为。如果没有错误发生,则可以执行负载测试。
图表
结果
网络在 15 分钟内部署完成并工作了约 1 小时 30 分,然后测试停止。进行了三次转账交易形式的负载会话。
显然,网络在负载测试启动之间是稳定的,节点 CPU 使用量不超过 20%。然而,与上一次测试相比,CPU 使用量有所增加。
结果和一些错误与上次测试也相似。
日志
该测试的日志片段在以下文件中给出:
2_1.log(在负载测试 1 期间)
2_2.log(在负载测试 1 启动后)
2_3.log(在负载测试 2 启动后)
2_4.log(在负载测试 3 启动后)
测试 3:49 个验证者,地理分布集群,稳定连接
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
regions:
Europe:
count: 20
type: large
Asia:
count: 20
type: large
North America:
count: 8
type: large
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
描述
该测试检查了具有 49 个验证者的网络的行为。验证者按地理分布。
图表
结果
网络在 15 分钟内部署完成并工作了约 1 小时,然后测试停止。进行了两次转账交易形式的负载会话。
结果与上次测试类似。网络的地理分布并未影响其稳定性。网络表现稳定,没有错误(除前述错误外,它们仍然存在),验证者只在负载启动之初失去了最终确认。
日志
该测试的日志片段在以下文件中给出:
测试 4:49 个验证者,本地化集群,3% 包丢失
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
packet loss: 3
producer:
count: 48
type: large
packet loss: 3
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 400, total-tx: 100000
profile: transfer
4) tps: 20, total-tx: 100000
profile: transfer
描述
该测试检查了具有 49 个验证者的网络的行为。由于网络存在 3% 的包丢失,该测试将展示小的包丢失是否会影响网络稳定性。
图表
结果
网络在 14 分钟内部署完成并工作约 2 小时 30 分,然后测试停止。进行了四个转账交易形式的负载会话。
包丢失对验证者的 CPU 和 RAM 使用产生了影响。CPU 使用量在非交易模式下增至近 20%,内存使用量增加了 10-20%。
该测试包含 3 个高负载交易会话和 1 个低 TPS(每秒 20 个交易)的大交易数量负载会话(100,000 个交易)。在这种负载下,平均 CPU 负载为 30-40%。网络继续完成区块,保持稳定工作。
在交易负载期间,验证者的日志如下:
无法发送验证交易结果:Ok
这可能是由于包丢失造成的。但是,这些日志不会影响整体网络稳定性。
日志
该测试的日志片段在以下文件中给出:
4_1.log(在网络启动后)
4_2.log(在负载测试 1 启动后)
4_3.log(在负载测试 2 启动后)
4_4.log(在负载测试 3 启动期间)
4_5.log(在负载测试 5 启动后)
测试 5 - 49 个验证者,本地化集群,5% 包丢失
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
packet loss: 5
producer:
count: 48
type: large
packet loss: 5
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 400, total-tx: 100000
profile: transfer
描述
该测试检查了具有 49 个验证者的网络的行为。由于网络存在 5% 的包丢失,该测试将展示小的包丢失是否会影响网络稳定性。
图表
结果
网络在 15 分钟内部署完成并工作约 2 小时,然后测试停止。进行了三次转账交易形式的负载会话。
结果几乎与上次测试相同。在交易负载下,验证者上仍有网络错误消息。然而,这几乎不会影响网络本身,但会增加活跃负载下的 CPU 负载。
日志
该测试的日志片段在以下文件中给出:
5_1.log(在网络启动后)
5_2.log(在负载测试 1 启动后)
5_3.log(在负载测试 2 启动后)
5_4.log(在负载测试 3 启动后)
测试 6:99 个验证者,本地化集群,稳定连接
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
count: 98
type: large
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 400, total-tx: 100000
profile: transfer
4) tps: 400, total-tx: 100000
profile: transfer
描述
该测试检查了具有 99 个验证者的网络的行为。
图表
结果
网络在 25 分钟内部署完成并工作约 4 小时,然后测试停止。进行了四个转账交易形式的负载会话。最后一会话模拟了持续负载。
结果与之前的结果没有区别。当内存池满时,验证者不再接受交易,而是将其标记为“交易无效”。
此外,在高负载下,一些验证者可能会失去连接,以下日志会弹出:
无法发送验证交易结果:Ok
一些验证者的 CPU 使用量在负载结束后没有减少。然而,其日志中没有观察到额外信息。
日志
该测试的日志片段在以下文件中给出:
6_1.log(在负载测试 1 启动后)
6_2.log(在负载测试 2 启动后)
6_3.log(在负载测试 3 启动后)
6_4.log(在负载测试 4 启动后)
6_5.log(在负载测试 5 启动后)
测试 7:100 个验证者,地理分布集群,稳定连接
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
regions:
Europe:
count: 33
type: large
Asia:
count: 33
type: large
North America:
count: 33
type: large
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 600, total-tx: 100000
profile: transfer
描述
该测试检查了具有 100 个验证者的地理分布网络的行为。
图表
结果
网络在 25 分钟内部署完成并工作约 3 小时,然后测试停止。进行了三个转账交易形式的负载会话。
地理分布并未影响网络稳定性。
与上次测试一样,一些验证者的 CPU 在负载结束后没有减少。然而,其日志中没有观察到额外信息。
在负载下仍存在无法连接的日志信息:
无法发送验证交易结果:Ok
日志
该测试的日志片段在以下文件中给出:
7_1.log(在负载测试 1 启动后)
7_2.log(在负载测试 2 启动后)
7_3.log(在负载测试 3 启动后)
测试 8 - 99 个验证者,本地化集群,7% 包丢失
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
packet loss: 7
producer:
count: 98
type: large
packet loss: 7
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
3) tps: 600, total-tx: 100000
profile: transfer
描述
该测试检查了具有 99 个验证者和 7% 包丢失的本地化网络的行为。
图表
结果
网络在 24 分钟内部署完成并工作了 1.5 小时,然后测试停止。进行了三次转账交易形式的负载会话。
7% 的包丢失影响了验证者空闲模式的 CPU 消耗,增加了 5%,并使得其中一个验证者在网络启动后未能立即同步(相反,它是在网络启动后 10 分钟后完成的)。
包丢失还导致一些验证者即使在没有负载的情况下也失去最终确认,但在一段时间后与之保持同步。
在负载结束后,CPU 的表现再次异常。由于某种原因,它在交易停止到达验证者后没有降低。
日志
该测试的日志片段在以下文件中给出:
8_1.log(在负载测试 1 启动前)
8_2.log(在负载测试 1 启动后)
8_3.log(在负载测试 2 启动后)
8_4.log(在负载测试 3 启动后)
测试 9 - 100 个验证者,地理分布集群,7% 包丢失
配置
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
packet loss: 7
producer:
regions:
Europe:
count: 33
type: large
packet loss: 7
Asia:
count: 33
type: large
packet loss: 7
North America:
count: 33
type: large
packet loss: 7
Tank.bench-polkadot
1) tps: 20, total-tx: 1000
profile: transfer
2) tps: 200, total-tx: 10000
profile: transfer
描述
该测试检查了由 100 个验证者组成并具有 7% 包丢失的地理分布网络的性能。此模式模拟了实际网络中集群之间距离相当遥远且包丢失很有可能的情况。
图表
结果
网络在 26 分钟内部署完成并工作了 2 小时,然后测试停止。进行了三个转账交易形式的负载会话。
集群的地理分布和 7% 的包丢失影响了验证者 CPU 在空闲模式下的消耗,几乎增加了 5%。一些验证者未能立即与网络同步,而是在网络启动后约 10 分钟。这个结果与之前的结果重复。
在负载结束后,CPU 再次表现奇怪。由于某种原因,它在交易停止到达验证者后未降低。
总体而言,网络运行正常。有趣的是,一些验证者的交易池无法很长时间排空(请参阅图表)。
日志
该测试的日志片段在以下文件中给出:
9_1.log(在负载测试 1 启动前)
9_2.log(在负载测试 1 启动后)
9_3.log(在负载测试 2 启动后)
9_4.log(在负载测试 3 启动后)
测试 10:31 个验证者,本地化集群,稳定连接
配置
Polkadot 版本:0.7.18
MixBytes.Tank
binding: polkadot
instances:
boot:
count: 1
type: large
producer:
count: 30
type: large
Tank.bench-polkadot
1,2) tps: 20, total-tx: 1000
profile: transfer
3) tps: 200, total-tx: 10000
profile: transfer
4) tps: 400, total-tx: 100000
profile: transfer
描述
该测试检查了由 31 个验证者组成的网络的性能。如果没有错误,负载测试将被执行。
图表
结果
网络在 11 分钟内部署完成并工作约 1 小时,然后测试停止。进行了三个转账交易形式的负载会话。
显然,网络在负载测试启动之间保持稳定,节点 CPU 使用量不超过 10%。在主动负载期间,一些节点的 CPU 消耗为 40%,其他节点为 10-20%。这种差异的原因不明。
网络通过了第一个负载测试(1000 总交易,10 tps),没有问题。未观察到错误。
第二个负载测试(10,000 总交易,200 tps)同样成功,然而,以下错误在负载模块上发生了一次:
第三个负载测试(100,000 总交易,400 tps)也成功。然而,即使在完成后,某些节点的 CPU 消耗仍未降低,仍然保持在 40%。原因尚未确定,日志已附上。
所有负载测试显示出大致相同的结果:第一个交易立即添加到区块中,这些区块迅速完成。在某些时刻,交易开始落入内存池并变得非常不情愿地接入区块。经过一段时间,内存池被清除。
日志
该测试的日志片段在以下文件中给出:
1.log(在负载测试 1 后)
2.log(在负载测试 2 后)
3.log(在负载测试 3 后)
结论
经过测试后,我们对 Polkadot 网络的性能得出了一些结论:
在测试版本 0.4.4 和 0.6.2 时,我们发现了几个错误,这些错误影响了验证者的正常运行。在某些情况下,网络无法在小型本地化集群中稳定生产和最终确认区块。低包丢失可能显著恶化验证者的功能。我们建议特别关注验证者之间区块和内存池的同步,以及在某些情况下的最终确认模式。所有提到的问题在版本 0.6.18 中得到修复,但限于交易包含率的问题。
版本 0.7.18 未显示出相较于版本 0.6.18 的稳定性改善。然而,负载模块不再显示在测试版本 0.6.18 时出现的一些错误。
网络承受相当强的交易负载。然而,一旦交易池满,验证者无法处理交易,直到池被排空。这可以视为防止垃圾邮件网络的保护,但你可以阻塞所有验证者池,从而停止网络(将无法发送交易)。
由于某种原因,交易加入区块的速度相当有限。
即使在高负载和网络包丢失的情况下,验证者在最终确认上的落后情况不超过 5 个区块。
新的方法(与低于 0.6 版本之前相比)通过 API 向验证者添加密钥不太方便,并需要额外的运维工作。
复杂的区块链软件开发涉及许多复杂性。在 Polkadot 的情况下,测试结果随着每个后续版本发布而改善。
MixBytes 是一支由区块链审计和安全研究专家组成的团队,专注于为 EVM 兼容和基于 Substrate 的项目提供全面的智能合约审计和技术咨询服务。请在 X 上关注我们,及时了解最新的行业趋势和见解。
- 原文链接: mixbytes.io/blog/polkado...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!