MQTT消息队列的云原生设计与应用实践

目录

1.MQTT协议简介

2.消息队列MQTT架构

3.K8S Operator

4.MQTT基于Operator的云原生实践

(1)部署MQTT集群

(2)MQTT集群集群的动态扩缩容

1)对于集群的动态扩缩容,存在以下几个步骤

2)MQTT Bridge基于MQTT Operator动态扩缩容效果(仅以CPU为监控指标为例)测试如下:

5.总结


1.MQTT协议简介

MQTT(Message Queuing Telemetry Transport)协议是一个客户端-服务器架构、基于发布/订阅机制的消息传输协议。它运行于 TCP/IP 之上,属于应用层协议。MQTT 最初由IBM 公司设计研发,并于2014年正式成为 OASIS 官方标准。

MQTT消息队列的云原生设计与应用实践_第1张图片

MQTT协议是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为简单、易于实现,CPU、内存等资源占用比较小的低开销、低贷款占用的即时通讯协议,MQTT被广泛应用于物联网、车辆网、智能家居、移动互联网等行业。

2.消息队列MQTT架构

MQTT是基于开源RocketMQ的架构做深入开发的,其整体架构如下图:

MQTT消息队列的云原生设计与应用实践_第2张图片

(1)RocketMQ 集群:用来作QoS>0 的消息和元数据的后端存储,同时为MQTT提供了路由管理、服务注册、服务发现的功能;

(2)MQTT Bridge 服务集群:由若干个无状态的 MQTT Bridge节点组成,MQTT Bridge节点之间的内存中订阅关系通过JGroup组播进行同步,以订阅树的形式保存在内存中,订阅树中保存了订阅关系和MQTT Bridge节点信息。其具体负责MQTT Bridge报文的解析、连接管理、消息路由转发、离线消息推送等对客户端的消息进行路由转发、对离线消息进行持久化等工作;

(3)Redis集群:保存持久化客户端的Session信息及离线消息的Offset;

(4)Iam集群:对MQTT Bridge集群提供鉴权服务,采用Raft协议保证集群的高可用;

(5)Measure集群:对MQTT Bridge集群提供计量采集服务,也是用Raft协议保证集群的高可用;每个客户端与MQTT Bridge集群保持长连接主要依靠心跳来维持。

3.K8S Operator

Operator 是用来扩展 Kubernetes API,特定的应用程序控制器,它用来创建、配置和管理复杂的有状态应用,如数据库、缓存和监控系统。Operator 是基于 Kubernetes 的资源和控制器概念之上构建,但同时又包含了应用程序特定的领域知识,是云原生领域生态发展的一种趋势。Operator能做到快速创建各种有状态中间件集群以及灰度发布,应用的全生命周期管理,实现容灾备份恢复,流量等指标监控、自动弹性扩缩容。

MQTT消息队列的云原生设计与应用实践_第3张图片


Operator 实现的关键是CRD(自定义资源)和 Controller(控制器)的设计,其工作原理是利用了 Kubernetes 的自定义 API 资源(如使用CRD,CustomResourceDefinition)来描述我们想要部署的“有状态应用”;在自定义控制器里,根据自定义 API 对象的变化,来完成具体的部署和运维工作。

4.MQTT基于Operator的云原生实践

通过消息队列MQTT的架构介绍,可了解到MQTT服务组件比较多,部署运维比较费时,且随着业务需求的增加或者减少,需要MQTT能够支持弹性扩缩容,保障业务能够合理利用资源。因此,采用MQTT Operator一键化快速部署MQTT消息队列集群,对MQTT集群进行弹性扩缩容至关重要。

下图是开发的MQTT Operator管理MQTT集群的架构图,其中MQTT Operator是用来扩展的 Kubernetes API,自定义的控制器,利用Kubernetes的List-watch机制,通过CRD的资源配置修改,触发MQTT Operator做对应操作,包括Statefulset、Deployment、Service、Configmap的创建,以及具体部署逻辑的修改,通过声明式API实现该功能。

MQTT消息队列的云原生设计与应用实践_第4张图片

  • Prometheus:一个开源监控解决方案,用于收集和聚合指标作为时间序列数据

  • Prometheus Adaptor:一种Kubernetes Resource Metrics API 和Custom Metrics API的实现

  • HPA,HPA :全称为(Horizontal Pod Autoscaling)根据当前 pod 资源的使用率(如 CPU、磁盘、内存等),进行副本数的动态的扩容与缩容,以便减轻各个 pod 的压力

(1)部署MQTT集群

MQTT operator可实现快速创建集群,只要把需要创建集群的名称、规模、资源大小等信息作为一个CR文件提交给MQTT Operator,MQTT Operator控制器会根据提交的期望达到状态进行检查协调直至拉起期望部署的MQTT集群,这与传统部署相比,不需要编写众多的部署文件,操作不易出错,效率得到极大提升。

(2)MQTT集群集群的动态扩缩容

1)对于集群的动态扩缩容,存在以下几个步骤

①Prometheus采集MQTT集群的自定义监控指标,比如TPS、连接数等

②Prometheus Adaptor根据配置的规则从Prometheus抓取并处理Metrics

③Metrics通过Custom Metrics API返回给HPA

④HPA通过获取的Metrics的value对MQTT Operator发送扩缩容请求

MQTT集群的动态扩缩容流程图:

MQTT消息队列的云原生设计与应用实践_第5张图片

2)MQTT Bridge基于MQTT Operator动态扩缩容效果(仅以CPU为监控指标为例)测试如下:

下图是使用MQTT Operator部署的MQTT集群

MQTT消息队列的云原生设计与应用实践_第6张图片

为了更快的达到MQTT Bridge的CPU瓶颈对MQTT Bridge 的CPU加以下限制,限制CPU最大分配200m:

resources:
  requests:
    cpu: 200m
  limits:
    cpu: 200m

①采用JMeter对集群进行连接数压测,同时连接3000个客户端,当没有实现弹性扩容时,JMeter的压测结果如下图,会有366个连接由于MQTT Bridge的 CPU达到瓶颈来不及处理CONNECT报文,不能及时返回CONNECT_ACK报文导致连接报错;

MQTT消息队列的云原生设计与应用实践_第7张图片

②采用JMeter对集群进行连接数压测,同时连接3000个客户端,当实现弹性扩容时,JMeter的压测结果如下图,当MQTT Bridge 的CPU达到一定的阈值会触发MQTT Operator对集群自动扩容,使连接负载到三个节点,所有的客户端都能正常连接,当客户端都断开,MQTT Bridge的自定义指标达到缩容的阈值时,会自动减少pod:

MQTT消息队列的云原生设计与应用实践_第8张图片

MQTT消息队列的云原生设计与应用实践_第9张图片

上述压测对比结果总结如下

序号 是否动态扩缩容 弹性扩缩容对比测试场景 测试结果说明
1 JMeter对集群并发连接3000个客户端 当MQTT Bridge在CPU达到一定的阈值会自动扩容,负载总连接数,最终3000个客户端成功连接服务
2 JMeter对集群并发连接3000个客户端 只有一台MQTT Bridge提供服务,3000连接并发会使CPU达到瓶颈导致来不及处理CONNECT报文,不能及时返回CONNECT_ACK报文连接报错
3 断开上述连接的客户端 当所有连接都断开后,CPU使用降低到设置的阈值,能缩容集群规模
4 断开上述连接的客户端 无变化

5.总结

本文介绍了MQTT协议、移动云消息队列MQTT的实现方案以及MQTT的云原生实践。后续移动云消息队列MQTT会支持增加新特性的MQTT 5.0.0协议,丰富更多的物联网/边缘端设备接入场景,比如点对点消息等。在云原生实践方面,其他中间件也可基于K8S Operator快速部署,自动运行配置、运维,面对类似的测试环境、开发环境,随用随部,甚至可以做成一个Operator平台,平台中嵌入各种中间件的K8S Operator,基于这个平台实现一键部署各种中间件,管理运维各类中间件。

本文作者:申栋

你可能感兴趣的:(java,网络,开发语言)