关注我们

电话:

(全国服务热线)400-003-3800 (售前电话)0736-7793-866 / 0736-7792-494
(售后电话)0736-7952-222 / 0736-7951-999

 

 

邮箱:

info@changdewm.com     

marketing@changdewm.com

地址:

湖南常德市武陵区青年路740号

OA系统                         outlook邮箱

 

新闻中心

NEWS

搭建基于Windows的水表行业高可用Socket通信服务框架

浏览量
张  景
(湖南常德牌水表制造有限公司,湖南常德 415000)
 
摘 要:随着城市化发展的速度越来越快,互联网以及互联网与传统水务行业相融合所产生的智能远传水表产品的使用日益增多,这就给互联网后台服务应用程序提出了更高的性能和并发要求。目前开发的后台服务应用程序中数据采集系统主要以基于TCP/IP协议的Socket编程技术构建。本文主要结合水表行业实际项目经验,阐述我是如何设计和开发一个高并发、高性能、高可用的网络通信框架。
关键字:水表 高可用 Socket 框架
       Socket服务器主要用于提供高效、稳定的数据处理、消息转发等服务,它直接决定了前台应用程序的性能。
       Socket通信从技术上分为客户端和服务端,目前客户端主要为无线远传集中器、有线远传集中器、单个物联网终端水表,实际上客户端在单微机上都只有一个Tcp客户端在连接。服务端Tcp连接包含长连接和短连接共存,随着用户量以及设备量的增加,一个高可用的Socket服务端技术的实现是非常重要的。
       直入主题,介绍我们的Socket通信服务框架,从架构上分为:网络层、业务层、数据层,其中在网络层增加了消息队列,在业务层加入业务抽象类处理不同的业务类型,在数据层引入SQL消息队列以及缓存数据库。具体如图:
(图一)WMSocket通信服务框架
(一)网络层
       网络层主要实现Socket连接的创建、消息接收、消息发送、关闭连接功能。作为Socket通信服务端,网络层的性能非常重要,所以我们在设计网络层的时候,着重的突破以下几方面:最大连接数、最大并发数、消息处理秒级别。主要通过如下几种技术和技巧解决:
1)使用基于IOCP模型的SAEA方式
       在Windows环境下利用Windows内核来进行I/O的调度,是用于Socket通信模式中性能最好的网络通信模型。Windows I/O Completion Ports完成端口技术的提出解决了“one-thread-per-client”即一个客户端连接就启动一个新的线程和客户端进行通信导致CPU在线程之间进行上下文切换所带来了负担的缺点,它充分利用内核对象的调度,仅仅只需要少量的几个线程来处理和客户端的所有通信,消除了无畏的上下文切换,从而最大限度的提升了网络通信的性能。
而在.NET环境下使用SAEA(SocketAsyncEventArgs)方式,重点在于池化,主要目的是避免在异步套接字I/O量非常大的情况下发生重复的对象分配和同步,提升性能和减少GC回收压力。
2)使用双工通信
       双工通信是提升Socket服务通信效率的一种有效技术方法。我们采用启动一个TcpSend线程调度器,在SAEA异步接收消息进行业务处理后,如果需要进行发送消息到客户端,采用向发送消息队列中Push一条消息,包含SAEA连接对象,通过TcpSend调度器轮询进行消息发送,以实现全双工通信。
3)消息队列及调度任务
       网络层消息队列主要为接收消息队列以及发送消息队列,主要目的在于提高Socket服务器的吞吐量。我们定义一个接收消息队列RecQueue和一个发送消息队列SendQueue,然后启动多个调度任务,不断的从消息队列中拿取消息,接收消息队列调度任务将消息拿取抛至业务层进行业务逻辑处理,发送消息队列调度任务拿取消息调用网络层发送消息接口,向指定客户端发送消息。
4)心跳扫描
       心跳分两种,一种为长连接客户端模式时由客户端定时发送心跳过来,服务端接收心跳消息,一旦超时没有心跳消息则判断客户端断开,服务端主动关闭该连接。另一种为服务端启动的定时心跳扫描,定时扫描每条连接,不论长连接还是短连接如果超过超时时间没有I/O响应,则关闭它,杜绝了挂掉的客户端成为落地生根的钉子户,占用系统资源。
5)粘包处理
       针对短连接不存在粘包情况,因为每次接收消息都要经过握手连接,接收消息,关闭连接。但是针对长连接,服务端在接收消息包时,就可能出现两条或多条消息一起接收了,而出现粘包情况。在这里我们采取了封装报文头和报文尾,并且加入报文长度位进行处理,来解决粘包的问题。
(二)业务层
       业务层接收到网络层调度任务抛过来的消息后,解决消息包,根据获取到的消息类型TYPE,通过抽象类转到相对对象的业务处理流程进行处理。
       业务处理流程通过单机或集群进行业务处理后,生成数据缓存实体,存入到Redis缓存数据库,以供Redis调度任务进行数据处理。
       同时业务层有发送消息时,根据具体的业务应用,封装不同功能的消息包,调用网络层消息发送接口,往网络层消息发送队列插入消息,以供网络层发送消息队列调度任务进行发送处理。
(三)数据层
       数据层的设计是整个Socket通信服务架构的关键。举个例子说明:假设我们的Socket服务器每秒均值处理2000条消息,每处理一条消息都会将数据作为历史记录存储到数据库,同时还要关联其他相关业务数据和表。那么数据层要想跟上网络层的处理性能,其执行SQL语句的效率也就必须达到每秒2000*n次,通常情况下我们的SQL语句的执行效率要达到那么高是很困难的。所以在整个Socket通信服务端,数据库的执行效率是瓶颈!
       那么如何提高数据库的执行效率,让数据层的处理速度和网络层的处理速度达到一个平衡?我们的设计是分两步走:首先采用高效内存数据库Redis+异步数据存储处理方式,确保通过高效的内存数据库Redis跟上网络层的处理速度;然后异步数据存储,通过DB连接池+SQL消息队列+SQL调度任务批量处理,通过稳定平衡的利用数据库空闲时间的处理来降低数据库硬盘存储数据的压力。
结论
以上架构设计完成后,通过测试发现:一台4G内存,2.4G主频,2处理器CPU的单机,接收客户端连接为32000时出现拒绝连接。也就是说在该服务器资源情况下,最多能接收到32000个连接数,按照一个采集设备至少负载1000台智能水表算,该服务器资源情况下至少能满足3000万台无线远传水表的接入和数据上传,完全能够满足一个大省(如湖南省)的智能远传水表的接入。
 
参考文献:
[1] 杨秋黎,金智.Windows网络编程(第2版).人民邮电出版社,2016.
[2] 胡萍,陈志鹏. 基于线程池的高性能服务器软件的设计与实现. 计算机技术与发展. 2006.
[3] [美]Josiah L. Carlson,黄健宏译. Redis In Action. 中国工业出版集团,2015.
[4] 刘伟. 设计模式(重点大学软件工程规划系列教材).清华大学出版社,2011.
[5] 黄晓君,周志斌. 浅谈远传水表系统. 科技信息学术版,2008(16):260+262.