付学良,李德军
(南京国电南自电网自动化有限公司,南京 210000)
配电网作为输配电系统的最后一个环节,其自动化程度与供电可靠性密切相关。配电自动化是改进供电质量、提高供电可靠性、扩大供电能力、实现配电网高效经济运行的重要手段[1]。与调度自动化系统相比,配电自动化系统的数据采集存在以下特点:(1)配电网数据采集量大,采集频率较低,中型系统采集量已超过20万点;(2)主站与终端设备直接通信,通信链路数随监控设备增加而大幅增加;(3)存在基于公网的数据采集;(4)系统的典型部署模式是地县一体。由此可见,配电网大数据采集成为配电自动化系统的一项关键技术[2]。Linux下的epoll机制是处理高并发(High concurrency)的成功模型,其与Windows下完成端口(IOCP)机制,都是I/O复用,都是异步消息事件的通知机制。将基于epoll机制的设计模型应用于大规模tcp连接,互联网方面的成功案例很多,但应用于电力自动化的少之又少,epoll模型成功用于配电自动化采集,对配电自动化的快速发展,以及后续的大数据分析有积极意义。
目前,Linux下I/O多路复用机制主要有3种:select,poll和epoll。 I/O多路复用就是通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为它们都需要在读写事件就绪后自己负责读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责读写,异步I/O会负责把数据从内核拷贝到用户空间[3]。表1简要列出了三者的区别。
epoll是Linux内核为处理大批量文件描述符而做了改进的poll,是Linux下多路复用I/O接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃情况下系统中央处理器(CPU)的利用率。另一点原因是,获取事件时它无须遍历整个被侦听的描述符集,只要遍历那些被内核I/O事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种I/O事件的水平触发(Level triggered)外,还提供了边缘触发(Edge triggered),这就使得用户空间程序有可能缓存I/O状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率[4]。
与传统电力信息采集服务器模型不同,大规模配电终端采集面临连接终端数量多、信息量大、通信链路不稳定的问题,同时还必须保证数据响应的快速性和可靠性[5]。基于以上特性,本文提出了一种基于epoll机制,采用多线程同步技术、超时异常处理技术的海量通信连接处理模型。采用epoll机制解决了海量配电终端网络通信以及效率和可靠性问题;超时异常处理技术解决了作为客户端连接时,epoll模型的稳定性问题;多线程同步中的互斥锁技术很好地解决了数据处理过程中的效率和稳定性问题[6]。
表1 select,poll与epoll区别[3]
海量配电终端信息处理模型由网络通信层、数据处理层和消息队列3部分组成。网络通信层为主线程,专门负责epoll的维护、配电终端数据接收,推送数据到消息队列。数据处理层主要负责处理消息队列的数据,此部分由多个线程共同处理,每个线程定期扫描对应的消息队列,有数据时进行处理,相当于数据的消费过程。消息队列与数据线程一一对应,每个数据线程只处理自己对应消息队列的数据。此模型将网络信息获取和信息处理分离,用共享数据队列作为二者的交换介质,用互斥锁来控制二者的访问权限,保证了数据接受的完整性和时效性。海量配电终端信息处理模型如图1所示。
图1 海量配电终端信息处理模型
一般情况下,创建1个线程是不能提高程序执行效率的,所以要创建多个线程。但是,多个线程同时运行时可能调用线程函数,在多个线程同时对同一个内存地址进行写入,由于CPU时间调度上的问题,写入数据会被多次覆盖,导致后续数据读取异常,甚至程序的异常中断退出。
基于上述问题,多线程对同一资源访问时,采用线程同步机制中的互斥锁技术来控制处理数据的写入。主线程接收到配电终端发送的实时数据,相当于生产者,信息处理线程负责处理数据,相当于消费者。对于每个缓冲队列定义一个互斥锁,当网络通信线程收到终端发送的1条数据时,申请对其中某一个队列加锁,然后将数据加入到此队列中,之后解锁。当对应处理线程开始工作后,申请对此队列加锁,发现队列中存在数据,对此数据记性处理,之后解锁。多个线程以此类推。
传统epoll模型大多针对服务器端,而配电终端采集不仅仅要考虑服务器模式,还要考虑批量客户端模式。例如,北京电力科学研究院历年针对配电主站国网的测试中,数据采集规约采用IEC60870-5-104《配电自动化系统应用DL/T 634.5104—2009实施细则》,此规约需要配电主站采集侧作为客户端,原有的epoll服务器端模式无法满足要求。本文在原有服务器模式基础上,设计了客户端模型,实现了服务端和客户端并存的信息采集模型。
此模型在不影响服务端工作的基础上,创建打开线程来定期连接海量配电终端,根据epoll产生的回调事件来判断与终端连接是否成功。但在不同的操作系统中,由于协议栈机制问题,并不是每个定期连接都会产生回调事件,在此引入超时异常处理机制,将超时还未产生回调的连接终端加入到超时队列中,作为epoll的异常处理fd,将其从epoll文件描述符集合中删除,从而保证了epoll文件描述符集合的正确性和稳定性。
在ubuntu12.04服务器上,本文提出了海量配电终端信息处理模型的实现方法,编写了一个海量配电终端信息采集和处理的服务软件。本服务软件直接调用Linux底层内核函数实现epoll机制,利用互斥锁实现线程同步,运行超时处理机制实现epoll稳定连接。服务端/客户端软件的基本流程如下。
(1)初始化,包括读取数据库中配置好的海量终端参数,创建互斥锁,创建处理线程。
(2)创建监听服务。
(3)创建epoll,初始化epoll,将本地监听的socket加入到epoll文件描述符集合中。
(4)创建打开线程,定期连接配电终端(服务端)。
(5)开始定期调用epoll_wait(),获取文件描述符事件数,并对所有事件逐个处理。事件主要分为接收配电终端连接事件、连接到配电终端事件、读写事件及错误事件,其中,可读事件负责进行数据接收处理。
(6)数据的处理线程在启动后以轮询的方式从缓冲队列获取数据,并进行相应处理。
(7)打开线程连接某个配电终端超时时,作为异常的epoll文件描述符处理,即从文件描述符集合中删除,并关闭对应socket,基本流程如图2所示。
图2 epoll机制C/S模型流程图
目前,陕西宝鸡采用的配电主站采集系统中,前置采集模块模型采集的是本文提出的epoll模型,采集服务器配置为Ubuntu 12.4,64G内存,CPU20核。现场已接入故障指示器、馈线终端设备(DTU)、配变终端设备(FTU)等配电终端达到2 000个,CPU占用率在5%左右,接入数据稳定、准确,并且时效性高。
本文研究了Linux epoll机制,并基于此机制研究了海量配电终端的信息采集模型,运用epoll经典服务模型,结合多线程同步技术和超时异常处理技术,解决了配电信息大容量采集的一个核心问题,既满足了作为服务端信息采集的高容量性,又满足了作为大批量客户端访问配电终端稳定性,保证了配电信息采集的安全性和时效性。本文采集模型已应用于陕西宝鸡配电网系统,证明了此模型的有效性和稳定性。