公司要改善opennms的流量检测功能。主要功能是:
- 封装配置文件,也就是操作thresholds.xml threshd-configuration.xml两个文件。
- 和通知功能联系起来。
我想主要三步走:
- 读懂源代码。(1-2天)
- 封装xml文件。需要先看明白xml的配置。封装可以参照对检测范围的封装。(2-3天)
- 联系通知功能能。(1-2天)
jmx : Java Management Extensions
一个复杂的软/硬件自身需要带管理功能,比如软件的设置。jmx就是方便管理的。
Sun公司JMX规定的架构图:
jmx分为四层:
- 设备层(Instrumentation Level):主要定义了信息模型。也就是被管理的信息资料,最简单的是一个变量的值。通常是一个接口*MBean,然后具体实现这个接口。方法多是set* get*管理属性。通过Agent Level的MBean Server注册,向上层提供接口。
- 代理层(Agent Level):主要定义了各种服务以及通信模型。该层的核心是一个MBean服务器,所有的管理构件(MBean)都需要向它注册,才能被管理。注册在MBean服务器上管理构件并不直接和远程应用程序进行通信,它们通过协议适配器和连接器进行通信。而协议适配器和连接器也以管理构件的形式向MBean服务器注册才能提供相应的服务。
- 分布服务层(Distributed Service Level):管理端,可以是web方式,也可以是专门的管理软件等。当前的JMX规范并没有给出这一层的具体规范。
- 附加管理协议API:定义的API主要用来支持当前已经存在的网络管理协议,如SNMP、TMN、CIM/WBEM等。
我感觉就是典型的客户-服务器模型。设备层提供被管理的信息,agent操作当地信息,service进行集中管理。只不过agent端将通信方式隔离出来。好比snmp服务,设备层好比被管理的数据库,比如sysDescr,agent就是snmp agent等。
JSR是独立的
简单的例子
设备层:
public interface HelloMBean {
// management attributes
public String getName();
public void setName(String name);
// management operations
public void print();
}
public class Hello implements HelloMBean {
private String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println("Hello, " + name + "!!" );
}
}
代理层注册:
// CREATE the MBeanServer
//
System.out.println("\n\tCREATE the MBeanServer.");
MBeanServer server = MBeanServerFactory.createMBeanServer();
// CREATE Registe HelloMBean
//
System.out.println("\n\tCREATE, REGISTER a new Hello Standard_MBean:");
HelloMBean helloMBean = new Hello();
ObjectName hello_name = null;
try {
hello_name = new ObjectName("Standard_Hello_MBeans:name=Hello,number=1");
System.out.println("\tOBJECT NAME = " + hello_name);
//将HelloMBean注册到MBeanServer中去
server.registerMBean(helloMBean, hello_name);
}
catch (Exception e) {
e.printStackTrace();
return;
}
然后管理端就可以管理name了
参考文档
http://www.jdon.com/concurrent/jmx.htm:入门的好材料。
http://www.huihoo.org/j2ee/jmx/:比较全面
thresd jmx分析
很简单的管理thresd进程的初始化、启动、结束、状态信息等等。ThresdMBean定义接口,Thresd实现这个接口。Thresd实现就是调用org.opennms.netmgt.threshd.Thresd类的相应函数,如:
public void start()
{
org.opennms.netmgt.threshd.Threshd.getInstance().start();
}
很简单。
xml文件的读如何分析
在 org.opennms.netmgt.ConfigFileConstants类中定义了各个xml配置文件的路径和名称。然后各自的*ConfigFactory(比如ThreshConfigFactory)读入xml配置文件,通过cator工具分析xml文件,存储在ThreshConfiguration(caseter根据配置文件(thresd-configuration.xsd?)自动生成的)类中。
threshd: 负责threshd进程的初始化,启动,停止等。
threshd初始化顺序:(init)
- 配置log4j
- 读取threshd-configuration.xml(ThreshConfigFactory)
- 读取thresholds.xml(ThresholdingConfigFactory)
- 读取poll-outages.xml
- 从数据库service中读取系统支持的所有服务
- 从threshd-configuration.xml中读取各个service的的threshholder,比如snmp协议的SnmpThresholder,ICMP、HTTP、HTTP-8000、HTTP-8080、DNS、DHCP,统一用接口LatencyThresholder 。存储在m_svcThresholders中。
- 启用调度程序m_scheduler
- 调度程序调度各个interface
- 依次从m_svcThresholders中读取某一service对应的thresholder
- 从数据库中读出所有支持该service所有node(ip)
- 对于每个node,通过scheduleInterface(nodeid,ipAddress,serviceName)调度该该node的该interface
- 从threshd-configuration.xml中读取中的内容,对于其中的每一项内容
- 创建一个ThresholdableService对象,并保存在m_thresholdableServices中以供event receiver使用
- 初始化对应的thresholder(此时根据thresholds中的内容配置thresholder,这样thresholder就可以据此比较产生事件了)
- 调度该Thresholder
- 创建event receiver(BroadcastEventProcessor),处理threshholder产生的事件
- 将进程状态设置成running
启动顺序(start):因为很多工作已经初始化的时候已经做了,所以启动比较简单
- 设置log4j
- 启动调度程序
- 设置状态为running
中止顺序(stop)
- 中止调度程序
- 中止event receiver
- 设置状态为stopped
暂停(pause)
- 暂停调度程序
- 设置状态
resume
- resume调度程序
- 设置状态
ThresholdEntity类
在threshold.xml配置文件中定义两个每个service的流量的最高值,最低值,如果超过这些数值一定的次数,就会发event.
castor(根据thresholding-config.xsd?)生成Threshhold类,包含配置信息。ThresholdEntry进一步封装。负责管理这些配置信息(最高值,最低值,次数等等)evaluate函数负责根据数值计算是否超过标准,等状态。
ServiceThresholder
流量检测检测每个具体服务的流量。这通过实现ServiceThresholder接口实现。具体由check()函数实现。
检测snmp服务的是ServiceThresholder。他先将数据保存,供rrd绘制图形。然后进行比较(根据ThresholdEntry类的evaluate函数),看是否需要产生事件。例如如果超过最高值就产生HIGH_THRESHOLD_EVENT
负责ICMP、HTTP、HTTP-8000、HTTP-8080、DNS、DHCP的是LatencyThresholder。
BroadcastEventProcessor负责处理事件
所有想获得eventd同志处理事件的需要实现org.opennms.netmgt.eventd.EventListener接口。 JMS topic session调用onEvent()实现对事件的处理。每个事件有唯一的Universal Event Identifier,据此可以进行不同的处理。
BroadcastEventProcessor主要是根据时间来更新所调度的thresholder.比如如果snmp interace变化,就需要先把旧的interface删掉,不再从该interface获取数据,然后在调度新的thresholder
StartService
提供main函数,启动threshd进程
ThresholdableService:用于BroadcastEventProcessor中,是否相当于event的过滤器,只有这些service的事件才通知?
在Threshd的init中调用scheduleExistingInterfaces调用scheduleInterface初始化,在生成BroadcastEventProcessor是作为参数传递进去。BroadcastEventProcessor在处理事件的事件使用,比如getThresholderUpdates()方法返回thresholderUpdates对象,然后可以处理snmp thresholder的变化
ThresholderUpdates: 用于封装snmpThresholder的改变。
总之,Threshd负责检查每个服务的流量。配置信息在xml中,ThresholdEntity 封装了配置信息,thresholder负责具体的检测,如果异常产生事件。事件会被多方接收到,BroadcastEventProcessor负责根据事件更新thresholder等方式维持流量检测。
collectd 负责收集snmp信息。基本架构类似threshd。serviceCollector是收集数据的接口。snmpCollector实现了这个接口,提供collect函数。SNMPCollectorEntry用来存储collect的数据结构。BroadcastEventProcessor也是用来处理事件的。因此相应的有CollectableService类。CollectorUpdates封装对snmpCollector的改变。SnmpIfCollector SnmpNodeCollector实现了snmpHanlder的接口,具体实现通过joesnmp获取数据。此外还有一些封装oid node的数据结构
xml文件分析
threshd-configuration.xml配置系统需要检测那些服务,以及相应的thresholder.
ThreshdConfiguration{
threads int
packageList Al of Package{
name String
filter Filer{
content String
}
specificList Al of String ;
includeRange Al of IncludeRange{
begin String
end String
}
excludeRange Al of ExcludeRange{
begin String
end String
}
includeUrlRange String
serviceList Al of Service{
name String
interval long
userDefined String
satus String
parameterList Al of Parameter{
key String
value String
}
}
outageClanderList al of String
thresholderList Al of Thresholder{
service String
classname String
parameterList Al of Parameter{
key String
value String
}
}
}
interval设定多长时间检查一次。status表示是”on”还是”off”,“off“则该项无效。user-definded表示是否可以用户设置。具体的结构可以分析castor产生的类。但是不清楚user-defined控制什么?
class-name设定service的thresholder
thresholds.xml:配置阀值等,用于控制流量检测
ThresholdingConfig{
groupList Al of Group{
name String
rrdRepository String
thresholdList Al of Threshold{
type String
dsName String
dsType String
value double
rearm double
trigger int
}
}