热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

高度可扩展,EMQX5.0达成1亿MQTT连接

摘要物联网设备连接和部署规模的不断扩大,对物联网消息平台的可扩展性和健壮性提出了更高的要求。为了确认云原生分布式MQTT消息服务器EMQX的性能表现可以充分满足当今物联网连接规模的

摘要

物联网设备连接和部署规模的不断扩大,对物联网消息平台的可扩展性和健壮性提出了更高的要求。为了确认云原生分布式 MQTT 消息服务器 EMQX 的性能表现可以充分满足当今物联网连接规模的需求,我们在 23 个节点的 EMQX 集群上建立了 1 亿个 MQTT 连接,对 EMQX 的可扩展性进行了压力测试。

在本测试中,每个 MQTT 客户端订阅了一个唯一的通配符主题,这比直接主题需要更多的 CPU 资源。消息发布时,我们选择了一对一的发布者-订阅者拓扑模型,每秒处理消息可达 100 万条。此外,我们还比较了在使用两个不同的数据库后端——RLOG DB 和 Mnesia 时,最大订阅率如何随着集群大小的增加而变化。本文将详细介绍测试情况以及在此过程中面临的一些挑战。


背景介绍

EMQX 是一个高度可扩展的分布式开源 MQTT 消息服务器,基于 Erlang/OTP 平台开发,可支持数百万并发客户端。因此,EMQX 需要在集群节点之间持久化和复制各种数据,如 MQTT 主题及其订阅者、路由信息、ACL 规则、各种配置等等。为满足此类需求,从发布起,EMQX 就一直采用 Mnesia 作为数据库后端。

Mnesia 是基于 Erlang/OTP 的嵌入式 ACID 分布式数据库,使用全网状点对点 Erlang 分发来进行事务协调和复制。这一特性使其在水平扩展方面存在困难:节点越多,复制的数据就越多,写入任务协调的开销就越大,出现脑裂场景的风险也越大。

在 EMQX 5.0 中,我们尝试通过一个新的数据库后端类型——RLOG(Replication Log)来缓解此问题,其采用 Mria 实现。作为 Mnesia 数据库的扩展,Mria 定义了两种类型的节点来帮助其进行水平扩展:一种是核心节点,其行为与普通的 Mnesia 节点一样,参与写入事务;另一种是复制节点,不参与事务处理,将事务处理委托给核心节点,同时在本地保留数据的只读副本。因为参与其中的节点较少,这使得脑裂风险大大降低,并且减少了事务处理所需的协调。同时,由于所有节点都可以本地读取数据,可以实现只读数据的快速访问。

为了能够默认使用这个新的数据库后端,我们需要对其进行压力测试,验证其确实能够很好地进行水平扩展。我们建立了一个 23 节点的 EMQX 集群,保持 1 亿个并发连接,在发布者和订阅者之间平分,并以一对一的方式发布消息。此外,我们还将 RLOG DB 后端与传统的 Mnesia 后端进行了比较,并确认了 RLOG 的到达率的确比 Mnesia 更高。


测试方法

我们使用了 AWS CDK 来进行集群测试的部署和运行,其可以测试不同类型和数量的实例,还可以尝试使用 EMQX 的不同开发分支。感兴趣的读者可以在这个 Github 仓库中查看我们的脚本。我们在负载生成器节点(简称“loadgens”)中使用了我们的 emqtt-bench 工具生成具有各种选项的连接/发布/订阅流量,并使用 EMQX 的 Dashboard 和 Prometheus 来监控测试的进度和实例的健康状况。

我们用不同实例类型和数量进行了逐一测试。在最后几次测试中,我们决定对 EMQX 节点和 loadgen 使用 c6g.metal 实例,对集群使用”3+20”拓扑,即 3 个参与写入事务的核心节点,以及 20 个为只读副本并将写入委托给核心节点的复制节点。至于 loadgen,我们观察到发布者客户端需要的资源要远多于订阅者。如果仅连接和订阅 1 亿个连接,只需要 13 个 loadgen 实例;如果还需要进行发布,则需要 17 个。

测试架构

在这些测试中未使用任何负载均衡器,loadgen 直接连接到每个节点。为了让核心节点专门用于管理数据库事务,我们没有建立到这些核心节点的连接,每个 loadgen 客户端都以均匀分布的方式直接连接到每个节点,因此所有节点的连接数和资源使用情况大致相同。每个订阅者都订阅了 QoS 为 1 的 bench/%i/# 形式的通配符主题,其中 %i 代表每个订阅者的唯一编号。每个发布者都以 QoS 1 发布了 bench/%i/test 形式的主题,其中 %i 与订阅者的 %i 相同。这确保了每个发布者都只有一个订阅者。消息中的有效负载大小始终为 256 字节。

在测试中,我们首先连接了所有订阅者客户端,然后才开始连接发布者。只有在所有发布者都连接后,它们才开始每 90 秒进行一次消息发布。在本文报告的 1 亿连接测试中,订阅者和发布者连接到 broker 的速率为 16000 连接/秒,不过我们相信集群可以保持更高的连接速率。


测试中遇到的挑战

在对如此量级的连接和吞吐量进行试验的过程中,我们遇到了一些挑战并据此进行了相关调查,使性能瓶颈得到了改善。system_monitor 为我们跟踪 Erlang 进程中的内存和 CPU 使用情况提供了很大帮助,它可以称得上是“BEAM 进程的 htop”,让我们能够找到具有长消息队列、高内存和/或 CPU 使用率的进程。在集群测试期间观察到情况之后,我们利用它在 Mria 中进行了一些性能调优[1] [2] [3]。

在使用 Mria 进行的初始测试中,简单地说,复制机制基本上是要将所有事务记录到由复制节点订阅的一个隐藏的表中。这实际上在核心节点之间产生了一些网络开销,因为每个事务本质上都是“复制的”。在我们 fork 的 Erlang/OTP 代码中,我们添加了一个新的 Mnesia 模块,使我们能够更轻松地捕获所有提交的事务日志,不需要“复制”写入,大大减少了网络使用,让集群保持更高的连接和事务处理速率。在进行了这些优化后,我们进一步对集群进行了压力测试,并发现了新的瓶颈,需要进一步的性能调优[4] [5] [6]。

即使是我们的招牌测试工具也需要进行一些调整才能处理如此大量的连接和连接速率。为此我们进行了一些质量改进[7] [8] [9] [10]和性能优化[11] [12]。在我们的发布-订阅测试中,甚至专门建立了一个分支(不在当前的主干分支中),以便进一步降低内存的使用。


测试结果

1 亿 MQTT 连接测试结果

上面的动画展示了一对一发布-订阅测试的最终结果。我们建立了 1 亿个连接,其中 5000 万是订阅者,另外 5000 万是发布者。通过每 90 秒发布一次消息,我们可以看到平均入站和出站速率达到了每秒 100 万条以上。在发布高峰期,20 个复制节点(这些节点是连接的节点)中的每一个节点在发布过程中平均用到90% 的内存(约 113GiB)和约 97% 的 CPU(64 个 arm64 内核)。处理事务的 3 个核心节点使用 CPU 较少(使用率不到 1%),并且只使用了 28% 的内存(约 36GiB)。256 字节有效负载的发布过程中需要的网络流量在 240MB/s 到 290 MB/s 之间。在发布高峰期,loadgen 需要几乎全部内存(约 120GiB)和整个 CPU。


注意:在这个测试中,所有配对的发布者和订阅者碰巧都在同一个 broker 中,这并不是一个十分接近现实用例的理想场景。目前 EMQX 团队正在进行更多的测试,并将持续更新进展。


Grafana MQTT

为了将 RLOG 集群与等效的 Mnesia 集群进行比较,我们使用了另一种总连接数较少的拓扑:RLOG 使用 3 个核心节点+7 个复制节点,Mnesia 集群使用 10 个节点,其中 7 个节点进入连接。我们以不同速率进行连接和订阅,不进行发布。

下图展示了我们的测试结果。对于 Mnesia,连接和订阅节点的速度越快,观察到的“扁平化”行为就越多,即集群无法达到目标最大连接数,在这些测试中,目标最大连接数为 5000 万。而对于 RLOG,我们可以看到它能够达到更高的连接速率,而集群不会表现出这种扁平化行为。由此我们可以得出结论,使用 RLOG 的 Mria 在连接速率较高的情况下比我们过去采用的 Mnesia 后端性能表现更好。

Mnesia VS RLOG


结语

经过一系列测试并获得这些令人满意的结果之后,我们认为 Mria 提供的 RLOG 数据库后端可在 EMQX 5.0 中投入使用。它已经成为当前主分支中的默认数据库后端。


References

[1] - fix(performance): Move message queues to off_heap by k32 · Pull Request #43 · emqx/mria

[2] - perf(replicant): Improve performance of the agent and the replicant by k32 · Pull Request #44 · emqx/mria

[3] - fix(mria_status): Remove mria_status process by k32 · Pull Request #48 · emqx/mria

[4] - Store transactions in replayq in normal mode by k32 · Pull Request #65 · emqx/mria

[5] - feat: Remove redundand data from the mnesia ops by k32 · Pull Request #67 · emqx/mria

[6] - feat: Batch transaction imports by k32 · Pull Request #70 · emqx/mria

[7] - feat: add new waiting options for publishing by thalesmg · Pull Request #160 · emqx/emqtt-bench

[8] - feat: add option to retry connections by thalesmg · Pull Request #161 · emqx/emqtt-bench

[9] - Add support for rate control for 1000+ conns/s by qzhuyan · Pull Request #167 · emqx/emqtt-bench

[10] - support multi target hosts by qzhuyan · Pull Request #168 · emqx/emqtt-bench

[11] - feat: bump max procs to 16M by qzhuyan · Pull Request #138 · emqx/emqtt-bench

[12] - feat: tune gc for publishing by thalesmg · Pull Request #164 · emqx/emqtt-bench


版权声明: 本文为 EMQ 原创,转载请注明出处。

原文链接:https://www.emqx.com/zh/blog/reaching-100m-mqtt-connections-with-emqx-5-0




推荐阅读
  • 投融资周报 | Circle 达成 4 亿美元融资协议,唯一艺术平台 A 轮融资超千万美元 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 在C#编程中,数值结果的格式化展示是提高代码可读性和用户体验的重要手段。本文探讨了多种格式化方法和技巧,如使用格式说明符、自定义格式字符串等,以实现对数值结果的精确控制。通过实例演示,展示了如何灵活运用这些技术来满足不同的展示需求。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 2021年Java开发实战:当前时间戳转换方法详解与实用网址推荐
    在当前的就业市场中,金九银十过后,金三银四也即将到来。本文将分享一些实用的面试技巧和题目,特别是针对正在寻找新工作机会的Java开发者。作者在准备字节跳动的面试过程中积累了丰富的经验,并成功获得了Offer。文中详细介绍了如何将当前时间戳进行转换的方法,并推荐了一些实用的在线资源,帮助读者更好地应对技术面试。 ... [详细]
  • Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战?
    Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战? ... [详细]
  • 在CentOS 7上部署WebRTC网关Janus
    在CentOS 7上部署WebRTC网关Janus ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • ZeroMQ在云计算环境下的高效消息传递库第四章学习心得
    本章节深入探讨了ZeroMQ在云计算环境中的高效消息传递机制,涵盖客户端请求-响应模式、最近最少使用(LRU)队列、心跳检测、面向服务的队列、基于磁盘的离线队列以及主从备份服务等关键技术。此外,还介绍了无中间件的请求-响应架构,强调了这些技术在提升系统性能和可靠性方面的应用价值。个人理解方面,ZeroMQ通过这些机制有效解决了分布式系统中常见的通信延迟和数据一致性问题。 ... [详细]
  • 黄聪:MySQL主从复制配置,实现高效读写分离
    大型网站为应对高并发访问,不仅需要在前端实现分布式负载均衡,还需在数据业务和访问层采取有效措施。采用传统的数据结构已无法满足需求,通过配置MySQL主从复制,可实现高效的读写分离,显著提升系统性能和稳定性。 ... [详细]
  • 本文介绍如何使用命令行工具查看和解析 iOS 应用崩溃日志,包括 UUID 和错误代码位置的详细步骤。 ... [详细]
  • 本文详细介绍了在 Android 7.1 系统中调整屏幕分辨率和默认音量设置的方法。针对系统默认音量过大的问题,提供了具体的步骤来降低系统、铃声、媒体和闹钟的默认音量,以提升用户体验。此外,还涵盖了如何通过系统设置或使用第三方工具来优化屏幕分辨率,确保设备显示效果更加清晰和流畅。 ... [详细]
author-avatar
阿毛
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有