利用EMQX 5.0达到1亿个MQTT连接的目标

142 阅读7分钟

使用EMQX 5.0达到1亿个MQTT连接数

为了对我们的开源MQTT消息代理的可扩展性进行压力测试,我们在一个23个节点的EMQX集群上建立了100M的MQTT连接。在这篇文章中阅读更多内容。

物联网设备连接和部署的规模不断扩大,这就要求物联网消息传递平台具有大规模的可扩展性和强大的规模。为了对我们的开源MQTT消息代理EMQX的可扩展性进行压力测试,我们建立了1亿个MQTT连接到一个23个节点的EMQX集群。

在这个测试中,每个MQTT客户端订阅了一个独特的非通配符主题。在发布时,我们选择了1对1的发布者/订阅者拓扑结构,实现了每秒9万条消息的低恒定发布率,然后激起了消息的爆发,在峰值时达到每秒处理100万条消息。我们还比较了集群规模的增加对使用两种不同的数据库后端的最大订阅率的影响:运行在RLOG模式和普通Mnesia。在这里,我们将详细介绍我们的设置和我们在此过程中所面临的一些挑战。

简介

EMQX是一个开源的、高度可扩展的、用Erlang/OTP编写的分布式MQTT消息代理,可以支持数百万的并发客户端。因此,有必要在集群节点之间坚持和复制各种数据;例如,MQTT主题及其订阅者、路由信息、ACL规则、各种配置等等。 从一开始,EMQX就使用Mnesia作为 ,以满足此类需求的数据库后端。

Mnesia是一个内嵌的ACID分布式数据库,与Erlang/OTP配套。它使用全网对等的Erlang分布进行事务协调和复制。由于这一特点,它在横向扩展上有困难:节点和数据的副本越多,写交易协调的开销就越大,分裂大脑的风险也越大。

在EMQX 5.0中,我们试图通过一种新的DB模式来缓解这个问题,这种模式被称为RLOG(意为 "复制日志"),在Mria中实现。Mria是对Mnesia数据库的扩展,通过定义两种类型的节点来帮助它进行横向扩展:

  1. 核心节点,其行为与通常的Mnesia节点一样,并参与写交易。

  2. 复制节点,不参与交易,而是将交易委托给核心节点,同时在本地保留数据的只读副本。

这有助于降低大脑分裂的风险,并减少交易所需的协调,因为参与交易的节点较少,同时保持只读数据的快速访问,因为它在所有节点上都可用。

在决定将这个数据库后端作为我们新的默认配置之前,我们需要对它进行压力测试,并验证它确实能够在水平方向上很好地扩展。为此,我们进行了测试,一个23个节点的EMQX集群维持了1亿个并发连接,其中发布者和订阅者各占一半,并以一对一的方式以恒定的速度发布消息,同时也进行了积极的突发。我们还比较了RLOG DB模式和传统Mnesia的性能,证实了RLOG确实可以维持比Mnesia更高的到达率。

我们如何测试它

为了部署和运行我们的集群测试,我们使用了AWS CDK,这使我们能够试验不同的实例类型和数量以及EMQX的不同开发分支。你可以在这个GitHub repo中查看我们的脚本。在我们的负载生成器节点(简称*"loadgens"*)中,我们使用我们的emqtt-bench工具来生成具有各种选项的连接/发布/订阅的流量。 EMQX的DashboardPrometheus被用来监控测试的进展和实例的健康状况。

我们逐渐尝试了各种实例的类型和数量,在最后的运行中,我们决定在EMQX节点和负载源中使用c6g.metal 实例,并在我们的集群中使用 "3+20 "拓扑结构。3个 "核心 "类型的节点和20个 "复制者 "类型的节点。至于我们的负载机,我们观察到,发布者客户端需要的资源比订阅者多得多。为了连接和订阅1亿个连接,只需要13个loadgens实例;对于发布订阅,我们需要17个实例。

在这些测试中,我们没有使用任何负载均衡器。相反,每个loadgen客户端以均匀分布的方式直接连接到每个复制体节点,所以所有复制体的连接数和资源需求都差不多。为了让核心节点只用于管理数据库写交易,loadgens 没有连接到它们。

每个订阅的客户都订阅了一个形式为bench/%i/test ,服务质量为1的非通配符主题,其中%i 代表唯一的订阅者编号,每个发布者都以服务质量为1发布到形式为bench/%i/test ,与相应的订阅者的%i 相同的主题。这种模式确保每个发布者正好有一个订阅者。消息中有效载荷的大小始终是100字节。每个用户和每个发布者都连接到随机的经纪商,所以他们不一定连接到同一个服务器,这意味着平均有95%的消息在经纪商之间被转发。

在我们的测试中,我们首先连接了所有的发布者,然后才开始连接我们的订阅者。在所有发布者被连接后,他们每个人都开始每600秒发布一次,以创造一个每秒约90,000条发布信息的 "背景"。然后,我们在每个loadgen中产生了10个额外的发布者,他们负责针对1000个随机用户进行短时间的密集发布。他们向每个随机选择的用户发布10条QoS 0消息(100字节),重复这个过程1000次。在这里报告的100M连接测试中,用户和发布者连接到经纪人集群的速率在峰值时为20000次/秒,尽管我们相信集群可以维持更高的连接速率。

一路走来的挑战

在我们试验如此大量的连接和吞吐量时,我们遇到了一些挑战,并调查和改善了性能瓶颈。对于跟踪Erlang进程的内存和CPU使用情况,system_monitor 是一个相当有用的工具。它基本上是"htop for BEAM processes",使我们能够找到具有长消息队列、高内存和/或CPU使用率的进程,然后在Mria中根据我们观察到的情况进行一些性能调整[1][2][3]。关于这些进程的更多信息,请访问下面的GitHub链接。

在我们对Mria的最初测试中,在不涉及太多细节的情况下,复制机制基本上将所有事务记录到一个 "幻影 "Mnesia表,该表由复制节点订阅。这在核心节点之间产生了一些网络开销,因为每个交易基本上都是重复的。在我们的OTP分叉中,我们添加了一个新的Mnesia模块,使我们能够更容易地捕获所有提交的交易日志,消除了重复写入的需要,大大减少了网络使用,并允许集群维持更高的连接/交易率。在这些优化之后,在进一步给集群施加压力时,我们发现了新的瓶颈,促使我们进一步进行性能调整,如下面的链接所示。