起重机械远程监控 APP 实时监测模块设计

作者:赵炯/周影/周奇才/熊肖磊

摘 要:为了使远程起重机械设备状态监测功能更具便携性,设计并实现了一种面向Android移动终端的实时数据监测模块。对异步输入/ 输出技术进行了研究,设计出客户端与服务器的通信方案。为了减少资源消耗和提高并发处理能力,服务器使用 Netty 框架作为高性能通信基础、利用线程池与任务分发机制实现了业务处理逻辑、通过 Mybatis 框架实现数据库的访问,并使用 Spring 容器实现程序中各种对象依赖关系与生命周期管理。测试结果表明,该模块能在移动客户端上实时显示监测数据和设备运行状态,且服务器具有较高的并发连接能力。模块有较高的可重用性,并能有效地扩展现有监控系统的功能。

Abstract: A real-time data monitoring module for Android mobile terminal is designed and implemented to more conveniently monitor hoisting machinery remotely. Communication scheme between client and server is designed based on researching asynchronous input/output technology. To save resources and improve concurrent processing capability, the server is equipped with Netty framework as the basis of high-performance communication, thread pool and task distribution mechanism to achieve business processing logic, Mybatis framework for database access, and Spring container to develop dependency among various objects in program and manage lifecycle. The test results show that the module can display monitoring data and equipment running status in real time on mobile client, and the server has higher concurrent connection capability. Besides, the module is highly reusable and capable of extending functions of existing monitoringsystem.

关键词:远程监控;实时监测;Netty 框架;Android;移动互联网;NIO 技术

Keywords: remote control; real-time monitoring; Netty framework; Android; mobile Internet; NIO technology

0 概述

远程起重机械设备通常需要实时监测功能,要求可靠的实时数据通信,并通过数值和图表等形式直观展现设备的运行参数和状态信息。在手机上利用其便携的优势拓展现有的监控系统,可使工作人员能随时随地获得设备的状态信息。

在系统的设计过程中需要考虑手机面临的通信效率、能耗等实际问题。服务器也需要应对资源消耗、客户端连接数量、并发安全等问题。这其中主要的问题来自于客户端与服务器的通信手段及服务器的业务处理模式。

高性能的服务器多以异步通信来获得更高的并发连接数、更小的系统开销和更好的性能 [1]。本文在客户端与服务器通信技术的研究基础上,利用 Reactor 模式 [2]进行实时监测模块的开发。模块基于 Java 语言,基于NIO 的 Netty 框架,该框架在构建中间件 [3]、消息推送 [4]、远程过程调用 [5]、HTTP 服务器 [6] 等领域被广泛使用。

Android 操作系统作为主流移动操作系统,具有开源、开放的优点,本文选择其作为移动客户端的实现平台。

1 系统设计

1.1 通信方案选择

服务器与客户端实现实时数据传输是系统实现的关键技术。实时数据的传输有以下方案:

第一种方案是轮询,即使用 HTTP 请求定时向服务器请求数据,这种方案是无连接的,但也带来了明显的缺点,即需要不断向服务器发送请求,增加了流量消耗与手机耗电量,浪费了系统资源。

二是使用 TCP 连接实现双向通信。TCP 是面向连接的可靠通信协议。使用 TCP 的服务器按照 IO 方式可分为阻塞 IO 和非阻塞 IO。阻塞型 IO 服务器工作原理如图 1 所示,在收到客户端的连接请求后将会开启新线程管理该连接,线程中的 IO 操作是阻塞式的,即每个操作执行完毕前,该线程都会处于等待状态,当用户增加时,阻塞方式将会给服务器带来压力,服务器所能维持的连接数目受系统资源限制。

图 1 阻塞 IO 模式的 TCP 服务器模型

非阻塞 IO 基于 IO 多路复用 [7] 与事件驱动,将客户端连接注册到选择器上,可使用少量线程管理大量并发的网络连接,更好地利用了系统资源。采用非阻塞的通信方式,不要求阻塞等待 IO 操作,消除了大量连接导致的开销,提高了系统性能。在非阻塞模式基础上可引入图 2 所示的异步 Reactor 模式即采用单个线程实现客户端连接的事件管理。为了减少业务处理对线程的阻塞,将用户请求处理放入线程池中执行,执行完毕后向客户端写回结果。这种服务器模型线程不在通信时阻塞, 减少了 CPU 负载;通过少量线程能够管理大量连接, 并通过线程池技术降低了服务器新建线程的开销,这种模式适用于大量用户并发访问的情景,并具有很好的可伸缩性能。

图 2 Reactor 模式的服务器模型

综上所述,采用TCP 协议,以异步 I/O 作为通信基础,并以 Reactor 模式作为业务处理模型,具有较高可行性。

0.1 Netty 框架

服务器中可使用开源的 Netty 框架。Netty 是 JavaNIO 框架,提供异步的和事件驱动的网络通信功能, 可用于开发高性能、高可靠性的网络服务器和客户端程序 [8]。

Netty基于 Reactor模式,具体的实现上有自己的特点。EventLoop 是 Netty设计的一个抽象概念,可看作一个事件检测循环线程,检测通信事件。Netty 通过 2 个EventLoopGroup处理用户的请求,EventLoopGroup 可以看作一个 EventLoop线程组,负责管理 EventLoop 的申请和释放。服务器创建了 2个 EventLoopGroup即bossGroup与 workerGroup。bossGroup是一个负责接收客户端新连接的线程池,负责处理客户端的 TCP连接请求。WorkerGroup是负责通信读写操作的线程组,当IO 事件发生时,该线程组负责事件的处理。

通道是 Java NIO 的一个基本抽象,代表一个网络连接,所有的 IO 通过通道完成。每个通道中包含一个处理客户端 IO 事件的流水线——ChannelPipeline,注册了一系列 ChannelHandler 用以处理和传递 IO 事件,各种事件在这些 ChannelHandler 中链式传递,可以通过覆盖 ChannelHandler 的回调函数完成相应操作,也可动态添加或删除ChannelHandler,使得程序具有很高灵活性。

Netty 能够响应的输入事件包括:连接注册、连接激活、读数据、异常捕捉等,而输出事件则是会触发将来行为的操作事件,包括:打开或关闭到远端的连接、写数据、冲刷数据等。图 3 展示了 ChannelPipeline 中事件的传递模型。

图 3 Netty 通道事件的处理

2 模块实现方案

2.1 软件架构

服务器按功能可分通信层、业务逻辑层和数据服务层,通信层用于接收用户连接、并对客户的请求进行处理和封装,最后交由业务逻辑层进行处理。业务逻辑层通过调用数据服务层提供的数据接口完成相应处理,并将返回数据交给通信层发送,通信层与业务逻辑层基于消息与回调思想,处于自己的线程池中,避免了耦合。

Spring和 Mybatis框架大大提高了系统的模块化程度。Spring基于IoC(Inversion ofControl,控制反转)思想, 代替开发者控制并管理程序中对象间复杂的依赖 [9],在系统中用于对组件的对象进行管理。MyBatis是一个基于 Java的持久层框架,可使用简单的 XML或注解将Java 对象映射成数据库中的记录,用于数据服务层的查询服务。系统的通信层基于 Netty 框架,在处理用户的请求时需要一套组件处理用户请求,图 4 展示了服务器中通过 Spring 管理的各个模块和其相互作用。

图 4 通过 Spring 管理各模块

Spring 容器在系统的职责包括:

1) 初始化各模块,自动注入模块依赖的对象,并管理其生命周期。

2) 使用面向切面 [10](AOP,AspectOrientProgra-mming)思想实现日志系统以及某些事件发生时的处理机制。面向切面使用非侵入的动态代理进一步减少耦合。

3) 根据需要在运行过程中动态创建某些对象。如当客户端连接时动态创建 Netty服务器所需的ChannelHandler 实例,添加到客户连接的通道。

2.2 通信层

在通信层中,Netty 框架将客户一次请求的消息内容保存在缓冲中,该缓冲及其处理过程中产生的事件与异常将在 ChannelHandler 链当中传递,最后被抽象为可提交的任务。通信层的处理流程如图 5 所示。

其中,ReadTimeoutHandler 为 Netty 提供的检测客户端连接超时的 Handler,当长时间没有接收到用户消息时,将会生成超时异常。由于手机的 IP 地址通常通过运营商的 NAT(Network Address Translation,网络地址转换)进行维护,必须在过期时间内发送心跳包以防止客户端的 IP 被回收 [11]。TimeoutHandler 用于检测超时异常,并及时关闭超时用户的连接以节约资源。

LogHandler 是一个双向 ChannelHandler,用于记录日志。另一个重要的作用是在连接建立与关闭时自动创建和销毁客户会话。JsonFilter 继承自 Netty 框架提供的 JsonObject-Decoder 类, 能根据格式将客户端请求的字符串划分为 JSON 字符串序列, 并将这些字符串向下一级ChannelHandler 逐个传递,当用户的请求不符合 JSON 格式的标准时,将会产生异常,起到过滤不符合 JSON 要求的客户端请求的作用。

JsonRequestDecoder 继承自 Netty 框架提供的MessageToMessageDecoder,将客户端的请求字符串封装为一个自定义的请求对象,可使用 JSON 转换工具将字符串反序列化为请求对象。

DispatherHandler 为所有客户端连接共享,用于将请求进一步封装为抽象的可提交任务。它使用请求分发器将用户通道信息、请求提交给业务层。

ReleaseHandler 为 Netty 提供的资源回收功能, 处在进入服务器的 Handler 链的末尾,提高服务器的资源利用效率。

ObjectToByteBufEncoder 继 承 自 Netty的MessageToByteEncoder 类,处于服务器出口,负责将响应写入缓冲,以满足 Netty 发送数据的要求。

2.3 业务逻辑层

业务逻辑层采用了线程池与任务队列机制。客户端通道、任务分发器、工作线程池构成的任务分发机制如图 6 所示。

图 5 客户端请求在 Netty 中的处理

图 6 任务分发机制

请求分发器内持有请求处理器的映射管理器,映射管理器维护了请求操作与请求处理器的映射,调用处理器的接口方法,即可完成对请求的处理。请求分发器本身不处理请求,而是根据客户端的操作码与请求处理器的映射,获得相应请求处理器的接口方法, 并将这个调用过程连同客户请求的上下文及客户端的通信通道封装为一个任务,提交到任务队列。工作线程池从队列中提取任务进行处理,并通过通信层向客户端发送处理结果。

2.4 通信协议

客户端请求的通过 JSON 字符串进行传递,包含的字段 为 :requestId,opCode,sensorIds,userId,password 。其中 requestId为请求标识,当数据返回时用以区分其对应的请求;opCode为客户端的操作类型;sensorIds 用来传递客户端要查看的传感器参数的列表;userId和password作为客户端的认证参数,认证成功后方可赋予相应的操作权限。

客户端的操作指令包括用户验证、获取传感器数据、切换传感器列表、心跳包等类型,每一个操作指令用一个整数表示,包含自己的请求处理器,当业务逻辑层处理请求时,将会调用相应处理器的接口方法,完成处理。客户端和服务器在应用层采用了如下的交互协议:

1) 客户端建立 TCP 连接。服务器在内存中添加一个会话,保存这次连接的信息,但此时连接没有传输实时数据的权限。

2) 验证请求合法性。客户端将保存在内存中的用户名和密码发送给服务器,对于不合法的请求,服务器将在返回的 JSON字符串中将告知错误码,并主动关闭此次连接释放资源。

3) 开始数据请求。客户端告知服务器需要查看的传感器的 ID列表,实时数据服务程序从数据库或缓存中查询到的最新的实时数据序列化成 JSON字符串,并加入时间戳,发送给客户端。

4) 用户定时刷新数据,用户主动向服务器发送数据请求,服务器将实时数据发送给客户端。

5) 切换传感器列表。客户端切换要显示的数据将按照系统时间生成一个 requestId,再次向服务器发送一次请求,更新服务器会话中的传感器 ID。

请求分发器内持有请求处理器的映射管理器,映射管理器维护了请求操作与请求处理器的映射,调用处理器的接口方法,即可完成对请求的处理。请求分发器本身不处理请求,而是根据客户端的操作码与请求处理器的映射,获得相应请求处理器的接口方法, 并将这个调用过程连同客户请求的上下文及客户端的通信通道封装为一个任务,提交到任务队列。工作线程池从队列中提取任务进行处理,并通过通信层向客户端发送处理结果。

6) 用户切换传感器列表过后,按照 4)继续请求。客户端接收到数据包后,为了与上次请求迟到的数据包相区别,将检查 requestId 是否相符。

7) 当用户长时间无通信时,向服务器定时发送心跳包以防止客户端 IP被运营商回收。

8) 客户端主动关闭 TCP 连接,通信结束,服务器检测到这一事件,删除会话信息。

2.5客户端开发

起重机械通常由大量零部件构成,但是零件之间存在着一定的层级关系,可以按照零件树对大量零件进行组织,在程序内部以树的数据结构予以表示。另一方面,每台设备都有需要重点关注的关键零部件及传感器,这部分数据可以作为默认传感器列表进行集中展现。Android 客户端开发中使用了开源的图形框架hellocharts,并利用其提供的折线图展示实时数据与时间的关系。

3 系统测试

首先说明系统运行环境和采集设备对象的数据特性,然后给出测试操作方式和数据显示界面。

3.1 运行环境

系统测试环境下的监测对象为分布在各地的大型港口设备,每台设备上均安装了大量传感器。原有系统已经形成了数据采集、数据处理、数据传输、数据库管理系统等基本功能,本模块在传统的远程监控系统的架构之上,增加了面向 Android用户的 TCP服务器,具有良好的兼容性。整个服务器发布为 Jar 包,可直接在运行Java环境中。本系统服务器操作系统为WindowsServer2012, 运行在 Java8环境中, 采用的数据库为 SQLServer 2012。

3.2 客户端界面

首页主体为地图,在地图上标识了设备以及设备的状态。点击地图上的图标,将会显示点击图标,出现弹层,展示设备的信息并定时刷新设备的重要传感器的实时数据。系统可以图形界面形式展示实时数据。

4 结束语

本研究基于Android 系统实现了实时数据监测功能, 拓展了传统起重机械监控系统;利用 Reactor 模式开发了服务器,并使用了多种开源框架提高了系统可移植性。但该模块还存在改进空间。

1) 使用数据库存储实时数据可能是性能瓶颈,可以考虑在系统中开辟缓存区,在实时数据存入数据库的同时保持一个缓存,专门为实时数据服务提供快速的数据查询。

2) 本模块目前面向 Android平台,具有一定局限性,解决的办法是使用 Websocket[12]技术。如 Html5可用于跨平台开发,它提供的 Websocket协议可实现服务器向客户端主动发送信息。

参考文献

[1] 袁劲松 , 马旭东 . 基于阻塞与非阻塞 I/O 网络模型的 Java

语言实现 [J]. 计算机系统应用 , 2008, 17(9):98-101.

[2] Gokhale S, Gokhale A, Gray J, et al. Performanceanalysis

ofthereactorpatterninnetworkservices[C]//InternationalCon- ference on Parallel and Distributed Processing. IEEE Computer Society, 2006:382.

[3] 崔晓旻 . 基于 Netty的高可服务消息中间件的研究与实现

[D]. 成都:电子科技大学 , 2014.

[4] 代超 , 邓中亮 . 基于 Netty的面向移动终端的推送服务设计 [J]. 软件 , 2015, 36(12):1-4.

[5] 张艳军 , 王剑 , 叶晓平 , 等 . 基于 Netty 框架的高性能 RPC

通信系统的设计与实现 [J]. 工业控制计算机 , 2016, 29(5):

11-15.

[6] 金志国, 李炜. 基于Netty的HTTP客户端的设计与实现[J].

电信工程技术与标准化 , 2014,29(1):84-88.

[7] StevensWR,RagoSA.AdvancedProgrammingintheUNIX Environment, 3rd Edition[M], Addison-Wesley,2013.

[8] 李林锋 .Netty权威指南 [M]. 北京 : 电子工业出版社,2014.

[9] WALLS C.SpringinAction[M].3rded.Greenwich:Manning, 2011.

[10] Elrad T, Aksit M, Kiczales G, et al. Discussing aspects of AOP[J]. Communications of the Acm, 2001,44(10):33-38.

[11] Rahman M S, Uddin Y S, Rahman M S, et al. Usingadaptive

heartbeat rate on long-lived TCP connections[C]//International Conference on NETWORKING Systems and Security. IEEE, 2016.

[12] 陆晨 , 冯向阳 , 苏厚勤 . Html5WebSocket握手协议的研

究与实现 [J]. 计算机应用与软件 , 2015, 32(1):128-131.

作 者:周 影

==========================================================================

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180509G10WQZ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励