0引言
随着光纤保护系统在通信领域的广泛运用,建立一整套软、硬齐全的光层保护监控系统尤其重要。系统通过数据采集服务可以实时快速地获得各个光保护设备的及时数据,然后交给上层进行相应的处理。
数据采集服务是惟一面向光纤设备的接口服务层,每秒有相当大的数据吞吐量,因此数据采集服务的设计尤为关键,必须兼顾考虑设计的合理性、高效性和一致性。面对大量的数据交流,采集服务分多个模块,主要采用多点采集多线程的模式构建方式。各个模块分别完成不同的功能,通过由主线程创建许多与子模块对应的子线程,由单独的一个线程来分发数据给各个子线程,实现数据的同步处理,提高系统的效率和网元容量。
1 TCP/IP,UDP协议
数据采集服务需要大量的数据处理工作,从光设备中采集数据以及将数据转交给上层服务都需要一定的协议来完成。根据TCP和UDP不同的特点,选取可靠的TCP/IP通信方式连接采集服务与上层服务;选取效率较高的UDP通信方式连接采集服务及下层设备。以UDP为例,UDP通信模块在发送的时候,只是需要从UDP发送队列获取数据发给设备,而在接收的时候,将设备数据存放到UDP接收队列。
数据的发送和接收分别由两个不同的线程来完成。此外,还有一个单独的线程对接收队列的数据进行解包和分发,并根据返回的UDP命令代码或索引(track)的不同将数据分别放置到数据轮询返回队列、阈值轮询返回队列和读写设备返回队列,其模块结构如图1所示。
2数据轮询
由于光保护设备都是非智能的设备,只能被动地采集性能数据,不会主动地上报性能变化给管理软件,基于此,在软件设计中采用了数据轮询机制,独立出一个轮询模块来捕捉网络中的性能变化,弥补了设备的不足。在这个模块中要进行处理,去掉一些重复的数据,以减少与上层服务通信的数据量。在轮询过程中,要进行超时控制,对于超时的请求需要补叫。因此,对于所有的轮询都需要有缓冲列表存储,只有当得到回应后才删除请求。
数据轮询模块包括数据轮询线程、数据轮询返回处理线程、阈值轮询返回处理线程和切换命令超时处理线程。数据轮询模块结构图如图2所示。
2.1数据轮询线程
数据轮询线程是负责对设备进行轮询的线程。通过定时地发出读数据和读阈值命令来采集设备的性能、状态、告警和阈值信息,因此,轮询时间间隔必须很小,而且对性能和阈值轮询的周期要求有所不同,因为阈值的变化较少。该线程在轮询模块启动后,判断是否获得配置信息树的初始信息,如果是就开始轮询。
2.2阈值轮询返回处理线程
数据轮询线程按照阈值轮询的周期定期发送读光保护设备阈值的命令,设备在收到命令包后定期返回设备的阈值,这些阈值通过UDP模块的数据分发线程发送到阈值轮询返回队列,等待阈值轮询返回处理线程来处理。
阈值轮询返回处理线程则接收这些返回的阈值,通过比较全局配置信息树的前次轮询结果与当前返回结果来捕捉阈值的变化,并将这些变化写入告警队列,通过性能和告警模块将阈值变化事件发送到上层服务器。
2.3数据轮询返回处理线程
与阈值的轮询相似,数据轮询线程按照系统设定的轮询周期定期发送读光保护设备数据的命令,轮询周期一般为500 ms或1 s。设备在收到读数据的命令包后定期返回设备数据,这些数据通过UDP模块的数据分发线程发送到数据轮询返回队列,等待数据轮询返回处理线程来处理。数据轮询返回处理线程在接收到这些返回的数据后,通过比较全局配置信息树的前次轮询结果与当前返回结果来捕捉告警信息、状态变化事件及其他信息,并将这些变化写入告警队列,通过性能和告警模块将告警和事件发送到上层服务器。
在该线程中,对线路切换的处理比较特殊,由于发生线路切换时用户需要察看切换前整个过程中性能值的变化情况,并且需要该信息尽快返回到用户界面,因此,当发生线路切换时需要立即发送8个数据包读取40帧切换过程的性能信息,通过数据分析后取出最近一次切换前的性能信息作为切换事件的附加数据添加到告警队列。
2.4读切换命令超时处理线程
在数据轮询线程中读切换信息命令发生工作模式改变(即发生线路切换)时,连续发送8个数据包(即8个读切换命令)读取40帧与线路切换相关的性能数据,每个命令读取5帧数据。返回的40帧数据通过索引号来判别数据的先后关系,与数据帧的位置无关。在实际过程中可能还需要反复发送数据包才能完整地获得40帧数据。因此,在读切换命令超时处理线程中,在命令超时之前还要对未返回的数据包反复发送取切换命令,直到完全获得全部40帧数据才能分析处理。
读切换命令超时时间设置为5 s,5 s内反复读取切换信息直到全部40帧数据返回或者超时,如果超时则仅向告警队列添加切换事件而不附带性能数据。
在返回数据的分析处理中,首先找到40帧数据中4个索引号的最大值,并在索引号最大的一组(共10个)数据中找到刚发生切换之前的性能数据——即找到这组数据中工作模式与切换后的当前工作模式相同的一帧数据,这帧数据的前一帧数据就是刚刚发生切换之前的性能数据,将这些性能数据作为切换事件的附带数据,和切换事件一起写入告警队列,发往性能和告警模块,等待处理并发送到上层服务器。
3多线程的应用
数据轮询模块自身就属于一个单独的线程,用来完成数据采集模块中的性能和告警数据主动采集功能,为了保证对众多网元设备的快速采集,数据轮询模块内部又用了多个子线程分工协作。
虽然多个线程同时工作,可以在不占用大量CPU资源的情况下提高模块的执行效率,但是模块也存在着一个隐患,它有一个潜在问题,即数据采集服务中有许多共享资源,可能在某个时刻,某一个线程修改某一个信息,正好第二个线程的时间片也到了,也试图去修改同一个信息,此刻就发生了数据冲突,那么后果比较严重。
上述问题的出现主要是两个线程同时访问了一个共享的变量,为了避免这种问题的发生,要求在多个线程之间进行同步处理,保证一个线程访问共享资源时,其他线程不能访问该资源。为了达到该目的,这里最初使用Sleep函数,让线程睡眠片刻,避免多个线程同时访问同一资源,但经过实践发现,这样不仅浪费时间,依然没有解决同步的问题。
为了实现这种同步,系统采用了同步队列技术,即构造了一个队列,让多个线程分别向其中存人数据和取出数据。例如,通过数据轮询从下层设备得到多种性能数据,这是UDP接收线程的工作。该线程将接收到的UDP包添加到同步队列的队尾,然后再去接收新的数据,反复做同样的操作。存放在同步队列中的数据等待命令处理线程将其一一取出并加以分析,然后分派到各个模块类。
命令处理线程每次从队列头部取出数据,一次只能取出一个数据。同一时刻,只能有一个线程对同步队列进行操作。否则会出现操作不同步的问题,影响数据获得的正确性。例如,当接收线程向队尾写数据时,处理线程也从队头取数据,可能取出的数据正好是接收线程当前所写入的,这样得到的数据不但不完整,也破坏了原始得到的性能数据。解决的方法就是给同步队列设置一个互斥量(mutex),当某个线程对同步队列进行操作时,就设置互斥。
这样,其他线程想要使用队列资源时就会因为互斥量已被设置而处于等待中,直到共享资源得到释放。另外,同步队列还采用了生产者一消费者模型,保证向同步队列添加新数据时,队列有空间;向队列取数据时,队列中有数据,避免产生内存泄露等问题。实现方式是在队列中添加信号量spProducer和spConsumer,每当向队列添加数据时,调用spConsumer-》post();取出数据的时候,调用spProducer-》post()。
同步队列定义了一个基类CMosSynQueue,里面封装了同步互斥的基本操作。在采集服务中各个模块都运用了多线程,所以每个模块都定义了一个同步队列,全部派生于CMosSynQueue。
4跨平台的实现
为了加强系统的通用性,系统将平台的相关性转变为无关性。利用stlport库的可移植性,封装了普通类,使所有类都能够跨平台使用。这些类包括CMosDirec-tory,CMosSynQueue,CMosEvent,CMosFile,CMos-MutexLock,CMosRunThread,CMosReadWriteLock,CMosSemaphore,CMosSimpleLock,CMosThread,CMosTimedMutex,CMosTryMurex。
每个类中,通过宏来选择程序运行在哪个操作平台,例如,#if defined(_MoS_WIN32_)则在Windows操作系统中使用,#elif defined(_MOS_POSIX_)则表示在Linux系统中使用。经过封装,系统中所有的类都派生自这些类,这样就可以在多个平台上使用了。
5结语
数据采集模块在整个网络管理系统中占据着十分重要的地位。这里主要介绍了采集模块中一个很重要的模块,即数据轮询模块。轮询模块采用了多线程,针对多线程,提出了一种同步的方式,采用同步队列。为了使软件更具有移植性,系统主要采用了stlport类库,实现了跨平台。该模块已在实际的网管系统中得到了应用,取得了较好的效果。
编辑:jq
-
cpu
+关注
关注
68文章
10859浏览量
211682 -
UDP
+关注
关注
0文章
325浏览量
33934
发布评论请先 登录
相关推荐
评论