[导入]基于SNMP数据采集模块的设计和实现
作者: ecsun 链接:http://papa.javaeye.com/blog/226506 发表时间: 2008年08月11日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
网络管理通常包括配置、故障、性能、计费和安全5个方面的管理功能。网管系统通过数据采集模块采集各个被管设备中的对象,经处理后为各个网管应用程序所用。网络管理各个功能的实现,都是建立在对各种管理信息采集的基础之上,数据采集是实现网络管理的前提和基础。面对大量需要采集的管理信息,构建一个稳定高效的数据采集模块对于实施可靠的网络管理具有举足轻重的作用。目前,数据采集主要有如下几种方式:基于简单网络管理协议(SNMP)、基于网络探针 (Probe)、基于网络流(Net-flow)。由于SNMP协议已成为事实上的网络管理标准,受到众多网络设备厂商的支持,且有标准函数接口支持,实现简单,因此现在普遍采用SNMP进行网络管理系统开发。本文针对基于SNMP数据采集方式中存在的效率问题,提出了面向数据类型的采集策略,同时采用多线程技术实现对不同被管设备的访问,大大提高了数据采集的效率,并且减少了冗余数据的重复采集。
1 对象访问方法
MIB中的每个对象都有一个惟一的对象标识符(OID),该标识符由所在MIB树中的位置决定。通过SNMP获取被管对象的信息,实际上并不是访问一个MIB对象,而是访问对象的一个特定实例。由于对象类型有标量对象、表对象(行对象和列对象)之分,因此对于他们实例的访问存在差别。
1.1 标量对象
标量对象与其实例是一一对应的,即一个标量对象只有一个对象实例。为了统一对象实例的标识,同时区分对象和对象实例,SNMP规定不属于表的标量对象的实例标识符由他的对象标识符加上0组成。对于标量对象实例的访问,可以通过调用SNMP++类库(HP公司提供的SNMP开发包)中的 Snmp::get()函数来实现。
1.2 列对象
在MIB定义中,表对象和行对象的访问状态是“无法访问”。对于列对象来说,他的实例是一组用列对象标识符(ColumnOID)和行索引值 (RowIndexValue)联合标识的实例。列对象标识符,是用来惟一标识列对象的OID。行索引值由一个或多个列对象对应实例的值组成。
列对象的每一个实例可以看作是表中指定列对应位置的元素。表中元素的位置可以用行坐标和列坐标表示,相应地,列对象的行坐标可以用 RowIndexValue表示,列坐标用ColumnOID表示。同一列元素有相同Colum-nOID,同一行元素有相同 RowIndexValue。表中元素可以通过如下公式进行标识:Oid=ColumnOID+RowIndex-Value。SNMP定义了访问列对象实例的方法:顺序访问和随机访问。
(1) 顺序访问
MIB对象的标识符是按字典顺序排列的,对于他们的实例也是按字典顺序进行排列。利用这种特性,可以通过调用SNMP++类库中的Snmp:: get_next()函数遍历获得一列或一个表甚至是整个MIB的结构。这种方法适合在未知被管设备MIB结构的前提下搜索和访问对象。
(2) 随机访问
由于列对象实例由ColumnOID和RowIndexValue共同标识,所以先要根据被指定为行索引的列对象获取他(们)的实例值确定特定实例的RowIndexValue,在此基础上联合已知ColumnOID组成特定实例的完整Oid,据此利用Snmp::get()获取相应的值。这里要指出一点,行索引本身也是一个或多个列对象,所以先要分别遍历各个列对象的所有实例,然后根据特定实例所在列的位置确定出RowIndexValue (由同一位置的列对象实例值按指定顺序组成)。由于同一行元素具有相同RowIndexValue,只需遍历(利用Snmp::get_next()函数)某一列对象获取实例的完整Oid(利用Vb::get_old()函数),根据(Oid-ColumnOID)即可确定RowIndexOid。可见,随机访问列对象某个实例的过程其实是顺序访问列对象和标量对象访问的结合。
2 数据采集策略
管理站从被管设备中采集数据有两种方式:主动访问被管对象和被动接收告警信息。主动访问被管对象是指管理进程(管理站中)通过SNMP协议发起对被管对象的请求,被管设备中的代理进程则响应该请求。被动接收告警信息是指管理进程监听陷阱端口(通常为UDP162端口),接收来自代理的告警信息。代理进程会在预定义事件发生时向管理进程发出Trap报文。
对于主动访问来说,根据访问对象的性质,可以分为静态信息和动态信息。对于静态信息来说,一经配置基本上保持不变,因此没必要在每一次采集过程中都对他进行轮询操作,只有当他发生变化时进行必要的访问以保证信息的有效。对于动态信息来说,他是随着设备的运行情况做出相应的调整,以实时地反映设备的状态或是性能信息。为了能跟踪设备性能参数的变化情况或是及时反映设备的运行状态,有必要对被管对象进行轮询操作,但是这里就存在一个采集频率的问题。
数据采集频率的确定,是一个与网络带宽权衡的过程。采集频率过低,占用网络资源相对较少,但是数据的更新周期相对较大,不能反映参数的真实变化情况;采集频率过高,数据更新自然较快,但是在采集周期内所占用的网络资源就会很大,增加网络设备的负担,甚至有可能会影响到正常的网络通信。因此在确定数据采集的频率时,必须根据实际的网络带宽资源进行考虑,同时还要考虑被管设备中被管对象的数量。
在动态信息的访问过程中,还存在另一个问题。如果按照串行操作,依次访问所有设备的被管对象,由于对象数目众多,将会占用很长的处理时间(甚至超出既定的采集周期,这个问题也是确定采集频率需要考虑的),导致访问工作不能正常进行。为了保证管理进程能够在采集周期内完成对所有被管对象的访问,这里采用多线程技术来完成对象的访问工作。对于同一被管设备,采用独立的子线程进行访问,这样一来既可以保证在一定周期内完成对所有被管对象的访问,也使得各个子线程保持相对的独立性,互不干扰。
在对象访问过程中,为减少管理进程和代理进程之间报文交换的次数,可以将不同对象绑定到同一个协议数据单元(PDU)的变量列表中,或是采用SNMPv2中新增加的GetBulkRequest-PDU。文献[5]和[6]中还讨论了有效获取MIB对象的方法。
3 数据采集模块的设计和实现
针对不同的数据采集方式,采用不同线程来完成数据采集工作。
3.1 告警信息接收线程
对于告警信息的被动接收,管理进程单独开启一个线程用来专门监听陷阱端口,接收并处理所有来自网管代理的告警(Trap)消息。在网络管理过程中,无论在性能管理、故障管理、还是安全管理等功能域,告警功能都是很重要的。这里主要利用SNMP Trap机制实现实时告警功能。
3.2 静态信息获取线程
对于静态信息的采集,管理进程同样为他单独开启一个线程来进行静态信息的收集。由于静态信息不随设备的运行而变化(一般不进行手工设置,静态信息保持不变),就没有必要重复地访问这类信息。本线程就是依据这一点,在对所有静态对象访问一次之后,将采集到的管理信息入库存储。应用程序对这类数据的操作只需访问本地数据库即可。如此就减少了对非实时变化信息的访问,同时也减少了冗余信息的存储。要指出一点,静态信息的改变一般是由于手工配置引起的,因此需要跟踪配置操作对相应的信息做出及时的更新。
3.3 动态信息轮询线程
对于动态信息的采集,管理进程也开启一个主线程用来专门负责动态信息的轮询工作。为了保证数据的实时性,就需要按照一定的时问间隔定时访问被管对象以获取最新的数据。对有关数据进行统计和分析,就能掌握动态信息的变化趋势,为故障管理、性能管理、计费管理等网络管理功能提供必要的数据支持。
为了使访问工作在规定的时间间隔内完成,避免串行执行带来的长周期问题,采用多个轮询子线程各自负责属于自己的管理对象子集。所有轮询子线程的工作结束后,这一次的访问工作便完成,即轮询主线程进入等待,直到下一次轮询点的到来或是接收到终止轮询主线程的命令。
4 结语
数据采集模块是网管系统对整个网络实时有效、可靠管理的前提和基础。本文首先分析了利用SNMP++开发包实现MIB对象访问的方法。在此基础上,根据不同的数据采集对象性质,对数据采集策略进行了探讨,提出了面向不同对象类型采用多线程技术进行数据采集的方法。最后,结合实际开发工作,对数据采集模块(特别是其中的动态信息轮询线程)做了详细的介绍。本文提供了一个高效、稳定的数据采集方案,并已在实际的网管系统中得到应用,取得了较好的效果。
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
[新闻]MySpace称目前是收购创业公司良机
博客园首页 社区 新闻频道 小组 博问 网摘 闪存
文章来源:http://www.cnblogs.com/haipeng/archive/2008/08/11/1291653.html