天天看點

使用snmp4j實作trap告警

使用snmp4j實作trap告警

Snmp4j的trap處理的文章在網上看了一些不過都是淺嘗辄止,基本都是大概的講述了一下如何接收trap等簡單的技術。但是這些對于企業級的開發往往是不夠的,随着納入trap接收伺服器的裝置增加其接收到的trap資訊也是成級數增加的。這裡就需要我們對于這種大資料量的trap處理進行管理。本文不對trap的各種名詞進行解釋,需要有一定的snmp基礎知識及java程式設計知識了解。

一、整體設計思路

         由于trap可能瞬時資料量特别的大,是以我們可以采用接收與處理互相分離的設計方法。即開啟一個線程專門接收trap,接收到trap後不做任何處理直接放入一個隊列中。然後開啟另一個線程從隊列中取資料,将取得的資料派發給多線程的處理接口處理。符合我們上報條件的trap向前台推送告警并讓前台頁面展現。具體流程如下圖。

使用snmp4j實作trap告警

二、示例程式搭建

        本程式采用myeclipse開發,是以直接引用myeclipse的spring包即可。此外還需要snmp4j包,這裡就不提供下載下傳位址了。

         執行個體項目第一版的目錄結構如下圖

使用snmp4j實作trap告警

a) spring 配置檔案applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	<bean id="trapListener" class="com.hepan.listener.impl.SnmpTrapListener">
		<property name="ip" value="192.168.122.34"></property>
		<property name="port" value="162"></property>
	</bean>

</beans>
           

b)main方法類Start.java

package com.hepan;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.hepan.handler.SnmpTrapHandler;
import com.hepan.listener.impl.SnmpTrapListener;


/**
 * 啟動類
 * @author 何盼
 *
 */
public class Start {
	public static ApplicationContext fsxac;
	public static void main(String[] args) {
		fsxac = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//啟動處理線程
		new Thread(new SnmpTrapHandler()).start();
		//啟動監聽線程
		new Thread((SnmpTrapListener)fsxac.getBean("trapListener")).start();
		
	}
}
           

c) 隊列中心 QueueCenter.java

package com.hepan.queue;

import java.util.concurrent.LinkedBlockingQueue;

import org.snmp4j.CommandResponderEvent;

/**
 * 隊列中心存放原始trap記錄即接收到的CommandResponderEvent對象
 * @author 何盼
 *
 */
public class QueueCenter {
	private static LinkedBlockingQueue<CommandResponderEvent> trapQueue = new LinkedBlockingQueue<CommandResponderEvent>();

	
	/**
	 * 獲得trap隊列
	 * @return CommandResponderEvent
	 */
	public static LinkedBlockingQueue<CommandResponderEvent> getRespEvntMsg (){
		if(trapQueue==null){
			return new LinkedBlockingQueue<CommandResponderEvent>();
		}else{
			return trapQueue;
		}
	}

	/**
	 * 存入trap隊列
	 * @param message
	 * @throws InterruptedException
	 * 
	 * 
	 */
	public static void putRespEvntLogsQueue(CommandResponderEvent message) throws InterruptedException{
		trapQueue.put(message);
	}
}
           

d) 監聽接口ListenerInterface.java

package com.hepan.listener;

import org.snmp4j.CommandResponderEvent;

/**
 * 接收trap資訊類接口定義
 * @author 何盼
 *
 */
public interface ListenerInterface {
	/**
	 * 存入隊列方法
	 * @param respEvnt
	 */
	public void putMessage2Queue(CommandResponderEvent respEvnt );
	
	/**
	 * 初始化方法初始化監聽端口、ip等資訊,這些資訊需要從SPRING配置檔案中讀取
	 */
	public void init();
}
           

d) 監聽抽象AbstListener .java

package com.hepan.listener;

import org.snmp4j.CommandResponderEvent;

import com.hepan.queue.QueueCenter;

/**
 * 處理類的抽象方法
 * 
 * @author 何盼
 *
 */
public abstract class AbstListener implements ListenerInterface ,Runnable {

	@Override
	public void putMessage2Queue(CommandResponderEvent respEvnt) {
		try {
			QueueCenter.putRespEvntLogsQueue(respEvnt);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		init();
	}
	

}
           

f) 監聽具體實作方法類 SnmpTrapListener.java

package com.hepan.listener.impl;

import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

import com.hepan.listener.AbstListener;

/**
 * 監聽類
 * @author 何盼
 *
 */
public class SnmpTrapListener extends AbstListener implements CommandResponder{
	
	private String ip; //本地IP
	private String port; //監聽端口
	private Address listenAddress; //位址資訊
	private ThreadPool threadPool;
	private MultiThreadedMessageDispatcher dispatcher;
	@Override
	public void init() {
		try{
		threadPool=ThreadPool.create("Trap", 2); 
		dispatcher=new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
		listenAddress = GenericAddress.parse(System.getProperty(
				"snmp4j.listenAddress", "udp:" + ip + "/" + port));
		TransportMapping transport;
		// 對TCP與UDP協定進行處理
		if (listenAddress instanceof UdpAddress) {
			transport = new DefaultUdpTransportMapping(
					(UdpAddress) listenAddress);
		} else {
			transport = new DefaultTcpTransportMapping(
					(TcpAddress) listenAddress);
		}
		Snmp snmp = new Snmp(dispatcher, transport);
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
		USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
				MPv3.createLocalEngineID()), 0);
		SecurityModels.getInstance().addSecurityModel(usm);
		snmp.listen();
		snmp.addCommandResponder(this);
		
		System.out.println("啟動監聽成功");
		}catch (Exception e){
			System.out.println("snmp 初始化失敗");
			e.printStackTrace();
		}
	}
	
	
	//此方法為CommandResponder 接口實作方法用于監聽後的處理方法,将接收到的trap資訊入隊
	@Override
	public void processPdu(CommandResponderEvent CREvent) {
		System.out.println("in processPdu");
		this.putMessage2Queue(CREvent);
	}


	public String getIp() {
		return ip;
	}


	public void setIp(String ip) {
		this.ip = ip;
	}


	public String getPort() {
		return port;
	}


	public void setPort(String port) {
		this.port = port;
	}


	public Address getListenAddress() {
		return listenAddress;
	}


	public void setListenAddress(Address listenAddress) {
		this.listenAddress = listenAddress;
	}



}
           

g) 處理實作類 SnmpTrapHandler.java

package com.hepan.handler;

import org.snmp4j.CommandResponderEvent;

import com.hepan.queue.QueueCenter;

/**
 * 處理類
 * @author 何盼
 *
 */
public class SnmpTrapHandler implements Runnable{

	@Override
	public void run() {
		while(true){
			try {
				CommandResponderEvent resEvent=QueueCenter.getRespEvntMsg().take();
				
				System.out.println("event:"+resEvent);
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}
           

三、測試trap接收

a)首先啟動程式,運作Start.java得到如圖所示。

使用snmp4j實作trap告警

b)發送trap

        發送trap我們采用ibm為我們提供的SolarWinds的Trap Editor軟體,界面如下圖。

使用snmp4j實作trap告警

建立一個trap,然後點選發送按鈕。如圖下圖所示。

使用snmp4j實作trap告警

填入IP後即可發送模拟trap了,程式收到這條資訊後控制台的輸出結果如下圖說是

使用snmp4j實作trap告警

對于如何處理該條trap後面我會陸續完成

上一篇: snmp4j詳解
下一篇: 集合源碼

繼續閱讀