1. 引言
随着越来越多的工业设备接入物联网,因处理器能力、网络带宽等具有局限性,所以对其通信技术提出了更高的要求 [1]。作为网页标准的HTTP,已不能满足机器之间的大规模沟通,其请求/回答模式不再合适,取而代之的是发布/订阅模式 [1]。这种模式就是轻量级、可扩展的MQTT可以施展拳脚的舞台,MQTT技术在汽车软件、智能家居、智慧医疗等方面有着广泛的应用。近来MQTT的优势被深度发掘,当有大量的MQTT协议的用户数据和设备实时数据需要存储在服务器端,会使得设备与服务器的交互相当频繁,当服务器接收到大量的数据请求时,MQTT服务器可能会出现宕机等现象。因此,MQTT服务器的负载均衡问题变得突出。传统的单台MQTT服务器处理能力已无法适应现代物联网大量数据请求 [1] [2],所以需要部署服务器集群系统。对不同性能的MQTT服务器,如何给其分配最适合其性能的任务量,协同处理和合理分配外部请求等需要一个负载分配平衡系统。由此可见引入MQTT服务器的负载均衡显得尤为重要 [3]。
2. 概述
本文的方法在兼顾MQTT服务器成本的同时解决了MQTT服务器系统稳定性问题。利用动态负载数据平衡分配策略 [4],对消息队列、CPU利用率、内存利用率的比重系数进行分析,用权值修改函数update Weight(),对权值修改模块优化更新,把用户请求均衡地重定向到其它站点,让系统在不增加硬件投入的情况下发挥最大的效能。当出现高并发量但单台MQTT服务器无法满足需求时,传统方法需要高性能的服务器才可以获得额外的服务资源 [1] [5]。本文的方法是通过增加MQTT服务器的数量并增加MQTT服务器均衡算法就能解决问题。当一开始不知道到底需要多高性能的服务器才能够处理所有需要挂载在其下的设备的请求,每当有设备量增加时,本文通过计算与测试,准确的添加所需要的最高性价比的服务器。
3. 负载均衡器和消息队列
3.1. Nginx负载均衡器
本文通过对服务器连接算法进行优化,推出一种新的MQTT服务器动态负载均衡算法。新算法通过提取当前MQTT服务器的相关运行性能及状态参数,改变其权值计算公式计算出为对应的权值,能够实时根据后端服务器的运行状态和负载状况,实时优化用户数据的重新定向 [6]。各MQTT服务器发送权值至Nginx负载均衡器后,负载均衡模块中写入新权值,当有新的用户请求任务时,负载均衡器会根据各服务器的写入的新权值比例关系进行分发。动态负载均衡算法见图1所示:

Figure 1. Dynamic load balancing algorithm
图1. 动态负载均衡算法
3.2. 权值修改模块
权值修改模块运行在集群系统前端的Nginx负载均衡器之上,权值修改模块被嵌入到Nginx中 [5],为了能够较好的分发用户连接请求,与MQTT各服务器集群进行通信 [5],该模块需实现接收后台各服务器发送的权值,对此前保存的权值进行更新,此算法与的静态权值相比,更能够实时并精确反映各服务器真实的负载情况 [5];根据各服务器权值间比例关系将用户连接请求分发至合理的服务器。
Nginx负载均衡器需与下游客户端基于MQTT协议进行通信,但它与上游后端服务器的通讯是基于TCP的事件驱动架构的 [5]。Nginx负载均衡器向后端服务器发送用户请求时,需要stream模块中的具体负载均衡算法的配合,在后端服务器集群中选择出一台合适的服务器用来处理用户请求 [5] [7]。
对后端服务器动态权值的实时获取并更新,主要用到权值修改函数updateWeight(),在修改权值之前需对包含权值信息的peers指针加锁,完成修改后再解锁 [8]。
当负载均衡器分发用户请求时,会调用后端各台服务器的函数,重新对后端服务器进行选择。当负载均衡器启动以后,就绑定Socket通信端口建立UDP服务,对指定端口进行监听,同时用recv()函数接收后端服务器发送的权值信息。调用fork()函数创建子进程,建立并发服务器,以接收到的权值更新原来保存在后端的服务器权值信息,各服务器的权值是作为分发用户连接请求的依据。负载均衡器其工作的流程见图2所示:

Figure 2. Work flow chart of load balancer
图2. 负载均衡器的工作流程图
4. 主要设计
4.1. MQTT服务器权值的算法设计
在改进的负载均衡算法中,MQTT服务器集群中的各台服务器周期性的收集自身负载信息和连接数,得出权值后发送给Nginx负载均衡器,根据各服务器的权值和负载通过筛选 [9],计算出合理的服务器去应答新的用户数据连接请求。此新算法主要包含计算MQTT服务器的权值,以及服务器集群周期性计算与上传权值。
当前MQTT服务器加权最小连接算法,无法对服务器实际负载进行合理的分配,且权值是由人为凭经验设置,在负载分发时固定不会变,在本文提出的改进算法中,各MQTT服务器节点根据自身CPU利用率和内存使用率两个性能指标,从而反映出了服务器的实际负载情况,再结合当前用户连接数计算得出综合负载,最后根据综合负载得出各个服务器节点的权值。在改进的负载均衡算法中,为了防止频繁的计算和发送权值会影响MQTT服务器和负载均衡器的性能,各MQTT服务器需周期性的去计算自身权值,计算得出权值与上一周期的权值进行比较,若权值变化率不大于
的权值将不会发送至负载均衡器。选取T和
的值需经过实验验证得到。改进算法工作模型见图3所示:

Figure 3. Working model of improved algorithm
图3. 改进算法工作模型
4.2. 权值计算
权值计算公式如下:
其中SU是系统利用率,A为可动态调整的系数(不为0),AL(Si)是服务器的综合负载值 [10]。
选择两类指标作为确定负载情况的因素 [11],负载计算公式如下:
为连接数指标,表示单个服务器的连接数与平均值的比值。
为磁盘利用率,
为CPU利用率,
为内存利用率,
为工作进程数,
为响应时间。R表示各负载参数重要程度的一组系数。
从服务器的实时性能参数以及状态参数两类参数。服务器实时性能值计算如下:
为CPU利用率,内存利用率的比重系数,且
。
和
分别表示服务器
的CPU利用率,内存利用率。其中CPU利用率更能反映当前节点的实时性能,从而取
的值分别为0.6和0.4 [12] [13]。
4.3. 权值上报设计
当前负载均衡调度分为集中式调度和分布式调度两种,这两种调度方式都需要一个负载均衡器来作为核心节点进行任务分配 [9]。随着服务器集群节点的增加,会增加核心节点的参数收集和计算工作,负载分发及系统效率会大幅下降。新的权值计算实时采集各服务器权值并按设定的周期发至负载均衡器,经过计算后得出新的任务分配列表,新的分布式权值调度方式可以减少负载均衡器和各服务器之间的通信次数及核心节点的工作量,负载均衡策略采用分布式调度方式。在数据请求较多时,如果大量上传这类权值也会增加核心节点不必要的工作量,减少这类权值的发送可以提升核心节点负载分发效率,可以利用集群中各服务器在周期T内的变化程度,来决定当前权值是否发送至核心节点。权值变化率计算如公式所示。
1)
:当前服务器在
时刻的权值;
2)
:当前服务器在
时刻的权值;
3)
:当前服务器在一个发送周期内的权值变化率,其中
。
权值用最少上报策略,周期T内的权值变化率与预先设定的
值比较,当T内的权值变化率小于
值时,服务器将不会发送权值至核心节点,只在本地修改保存的权值信息。如果当前服务器权值变化率大于
,则将新权值发送至核心节点。在周期T内如果核心节点没有收到权值,则按前面保存的该服务器的权值分发负载。
5. 实验结果和分析
5.1. 实验环境
本文使用了三台八核高性能服务器搭载系统,服务器配置信息参数为:CPU主频为4.00 GHz,采用Intel(R) Core(TM) i7-4790K处理器,32 G内存,2 T硬盘,操作系统版本为Ubuntu 16.04.2。本文实验测试程序使用Java编写,JDK版本为1.8,Nginx使用1.13.9版本。通过开源压力测试工具Jmeter模拟终端设备大量的TCP连接,使用多台压测机器在局域网中对系统进行性能测试。压测机器使用3台四核CPU的计算机,其配置信息参数为:Intel(R) Core(TM) i5-7200U处理器,8 G内存,256 G固态硬盘,操作系统为Win10。实验在局域网中进行,机器间通过百兆交换机相连,因此本文实验不考虑带宽的影响。
5.2. 实验设计与分析
通过获取当前时刻的CPU的活动信息,分别为用户状态的运行时间、系统内核相关的运行时间、空闲状态的运行时间。CPU性能指标各项数据见表1所示:

Table 1. Data of CPU performance index
表1. CPU性能指标各项数据
Nginx收到连接请求后,通过添加代码来获取的后端服务器动态权值进行更新,对修改权值之前需对权值的指针加锁,修改完后解锁。主要加解锁函数代码见图4所示:
本文实验将基于WLC、基于WRR以及WRR改进的算法三种方案进行比较。通过测定各服务器的 CPU负载率,内存利用率接近程度可以比较直观地看出算法的负载均衡效果。
本文根据这三种算法方案进行测试。三种算法的响应时间见表2所示,并发请求相应时间对比图见图5所示:

Table 2. Response time of three algorithms
表2. 三种算法的响应时间

Figure 5. Corresponding time comparison of concurrent requests
图5. 并发请求相应时间对比图
当并发请求连接数为1500时,观察服务器的内存利用率和CPU利用率的接近度。CPU利用率图见图6,内存利用率见图7所示:
由此可得,在总体负载水平较轻时,改进算法相比加权最小连接算法的负载均衡效果提高并不明显 [14] [15],当MQTT服务器集群出现较重负载时,新的加权算法会按照集群中服务器的实时负载情况合理的分发用户连接请求,新的算法优化能使总体平均响应时间变短,根据上图实验数据可知,能够将负载更加均匀的分发至集群各服务器,负载差由原来的8%下降到4%左右,使MQTT服务器集群系统的使用效率提高了,因此在用户并发请求连接数较多时,本文新的权值算法提出的改进算法具有较好的实用价值。
6. 结论
本文主要提出了一种基于MQTT负载均衡算法的改进设计方案,从优化负载均衡入手,分析MQTT服务器权值的算法设计及权值上报设计,MQTT服务器集群中的各台服务器周期性地收集自身负载信息和连接数,得出权值后发送给Nginx负载均衡器,根据各服务器的权值和负载通过筛选,得出合适的服务器去应答新的用户数据连接请求。对服务器负载进行实时分析及负载的重新权值计算及分配,使系统负载更加均匀地分发至集群各服务器。
从多次实验及实际应用数据来看,对消息队列、CPU利用率、内存利用率的比重系数进行分析,利用权值修改函数updateWeight(),在修改权值之前对包含权值信息的peers指针加锁对权值修改模块优化更新,这种新的MQTT负载均衡算法能使各服务器之间的负载差下降,MQTT服务器集群系统的使用效率提高;因此在用户并发请求连接数较多时,总体平均响应时间将会有一程度的缩短,使MQTT服务器集群在一个较为稳定的工况下运行,防止出现数据堵塞而宕机等情况发生。
根据本方案设计的系统已投入智慧校园项目的使用,在实际场景的应用中未出现数据交互不稳定情况,且系统运行效果较好。
基金项目
本课题得到浙江理工大学本科生科研创新计划重点项目(2019ZD-28)、浙江理工大学本科生科研创新计划一般项目(2019YB-24)资助。