springboot中使用snmp4j對linux及windows系統進行資源情況監測

前言:上面兩篇博客已經分享了分別在windows和linux安裝snmp服務的教程,現在開始應用到springboot項目中去,用來監控服務器的內存CPU佔用率、磁盤大小、已使用、未使用的磁盤大小、網絡上行下行速率等,步驟如下:

1.導入maven包:

        <!--snmp4j-->
        <dependency>
            <groupId>org.snmp4j</groupId>
            <artifactId>snmp4j</artifactId>
            <version>2.5.11</version>
        </dependency>

2.Snmp工具類:

import com.alibaba.fastjson.JSON;
import com.cecjx.common.config.DictRedisConfig;
import com.cecjx.common.domain.DictDO;
import com.cecjx.oamonitor.domain.SnmpOid;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SnmpUtils {
    private static final Logger logger = Logger.getLogger(SnmpUtils.class);

    public static CommunityTarget createDefault(String ip, String community, String port) {
        if (StringUtils.isBlank(ip)) {
            throw new NullPointerException("ip is null.");
        }

        if (StringUtils.isBlank(community)) {
            throw new NullPointerException("community is null.");
        }

        Address address = GenericAddress.parse("udp:" + ip + "/" + port);
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(community));
        target.setAddress(address);
        target.setVersion(SnmpConstants.version2c);
        target.setTimeout(3000);
        target.setRetries(5);
        return target;
    }


    public static List<Map<String, String>> snmpGet(String ip, String community, String port, String oid) {
        if (StringUtils.isBlank(ip)) {
            throw new NullPointerException("ip is null.");
        }

        if (StringUtils.isBlank(community)) {
            throw new NullPointerException("community is null.");
        }

        List<Map<String, String>> list = null;
        CommunityTarget target = createDefault(ip, community, port);
        Snmp snmp = null;
        try {
            PDU pdu = new PDU();
            pdu.add(new VariableBinding(new OID(oid)));
            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();

            pdu.setType(PDU.GET);
            ResponseEvent respEvent = snmp.send(pdu, target);

            PDU response = respEvent.getResponse();
            if (null != response && response.size() > 0) {
                list = new ArrayList<Map<String, String>>();
                for (VariableBinding vb : response.getVariableBindings()) {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put(oid, vb.toValueString());
                    list.add(map);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            closeSnmp(snmp);
        }
        return list;
    }

    public static void snmpGetList(String ip, String community, String port, List<String> oidList) {
        if (StringUtils.isBlank(ip)) {
            throw new NullPointerException("ip is null.");
        }

        if (StringUtils.isBlank(community)) {
            throw new NullPointerException("community is null.");
        }

        if (null == oidList || oidList.isEmpty()) {
            throw new NullPointerException("oidList is null.");
        }

        CommunityTarget target = createDefault(ip, community, port);
        Snmp snmp = null;
        try {
            PDU pdu = new PDU();

            for (String oid : oidList) {
                pdu.add(new VariableBinding(new OID(oid)));
            }

            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();
            pdu.setType(PDU.GET);
            ResponseEvent respEvent = snmp.send(pdu, target);
            PDU response = respEvent.getResponse();
            if (null != response && response.size() > 0) {
                for (VariableBinding vb : response.getVariableBindings()) {
                    logger.info(vb.getOid() + " = " + vb.getVariable());
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            closeSnmp(snmp);
        }
    }

    public static void snmpAsynGetList(String ip, String community, String port, List<String> oidList) {
        if (StringUtils.isBlank(ip)) {
            throw new NullPointerException("ip is null.");
        }

        if (StringUtils.isBlank(community)) {
            throw new NullPointerException("community is null.");
        }

        if (null == oidList || oidList.isEmpty()) {
            throw new NullPointerException("oidList is null.");
        }

        CommunityTarget target = createDefault(ip, community, port);
        Snmp snmp = null;
        try {
            PDU pdu = new PDU();

            for (String oid : oidList) {
                pdu.add(new VariableBinding(new OID(oid)));
            }

            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();
            pdu.setType(PDU.GET);

            /*異步獲取*/
            final CountDownLatch latch = new CountDownLatch(1);
            ResponseListener listener = new ResponseListener() {
                @Override
                public void onResponse(ResponseEvent event) {
                    ((Snmp) event.getSource()).cancel(event.getRequest(), this);
                    PDU response = event.getResponse();
                    if (null != response && response.size() > 0) {
                        for (VariableBinding vb : response.getVariableBindings()) {
                            logger.info(vb.getOid() + " = " + vb.getVariable());
                        }
                        latch.countDown();
                    }
                }
            };

            pdu.setType(PDU.GET);
            snmp.send(pdu, target, null, listener);
            boolean wait = latch.await(30, TimeUnit.SECONDS);
            snmp.close();
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            closeSnmp(snmp);
        }
    }

    public static Map<String, String> snmpWalk(String ip, String community, String port, String targetOid) {
        CommunityTarget target = createDefault(ip, community, port);
        TransportMapping transport = null;
        Snmp snmp = null;
        Map<String, String> map = new HashMap();
        try {
            transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            transport.listen();

            PDU pdu = new PDU();
            OID targetOID = new OID(targetOid);
            pdu.add(new VariableBinding(targetOID));

            boolean finished = false;
            while (!finished) {
                VariableBinding vb = null;
                ResponseEvent respEvent = snmp.getNext(pdu, target);

                PDU response = respEvent.getResponse();

                if (null == response) {
                    System.out.println("responsePDU == null");
                    finished = true;
                    break;
                } else {
                    vb = response.get(0);
                }
                finished = checkWalkFinished(targetOID, pdu, vb);
                if (!finished) {
                    logger.info(vb.getOid() + " = " + vb.getVariable());
                    pdu.setRequestID(new Integer32(0));
                    pdu.set(0, vb);
                    map.put(vb.getOid().toString(), vb.getVariable().toString());
                } else {
                    snmp.close();
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            closeSnmp(snmp);
        }
        return map;
    }

    public static void closeSnmp(Snmp snmp) {
        try {
            if (null != snmp) {
                snmp.close();
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    private static boolean checkWalkFinished(OID targetOID, PDU pdu, VariableBinding vb) {
        boolean finished = false;
        if (pdu.getErrorStatus() != 0) {
            logger.info("[true] responsePDU.getErrorStatus() != 0");
            logger.info(pdu.getErrorStatusText());
            finished = true;
        } else if (vb.getOid() == null) {
            logger.info("[true] vb.getOid() == null");
            finished = true;
        } else if (vb.getOid().size() < targetOID.size()) {
            logger.info("[true] vb.getOid().size() < targetOID.size()");
            finished = true;
        } else if (targetOID.leftMostCompare(targetOID.size(), vb.getOid()) != 0) {
            logger.info("[true] targetOID.leftMostCompare() != 0");
            finished = true;
        } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {
            logger.info("[true] Null.isExceptionSyntax(vb.getVariable().getSyntax())");
            finished = true;
        } else if (vb.getOid().compareTo(targetOID) <= 0) {
            logger.info("[true] Variable received is not " + "lexicographic successor of requested " + "one:");
            logger.info(vb.toString() + " <= " + targetOID);
            finished = true;
        }
        return finished;

    }

    public static String getPrintSize(long size) {
        //如果字節數少於1024,則直接以B爲單位,否則先除於1024,後3位因太少無意義
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        //如果原字節數除於1024之後,少於1024,則可以直接以KB作爲單位
        //因爲還沒有到達要使用另一個單位的時候
        //接下去以此類推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            //因爲如果以MB爲單位的話,要保留最後1位小數,
            //因此,把此數乘以100之後再取餘
            size = size * 100;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "MB";
        } else {
            //否則如果要以GB爲單位的,先除於1024再作同樣的處理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "GB";
        }
    }

    //從redis獲取字典表裏的oid數據
    public static SnmpOid getOid(RedisUtil redisUtil, String oidType) {
        SnmpOid snmpOid = new SnmpOid();
        Object obj = redisUtil.getObject(DictRedisConfig.dictResisPrefix + oidType);
        List<DictDO> oidList = JSON.parseArray(redisUtil.getObject(DictRedisConfig.dictResisPrefix + oidType).toString(), DictDO.class);
        if (oidList.size() > 0) {
            for (DictDO dictDO : oidList) {
                switch (dictDO.getName()) {
                    case "sysDescOid":
                        snmpOid.setSysDescOid(dictDO.getValue());
                        break;
                    case "ramTotalOid":
                        snmpOid.setRamTotalOid(dictDO.getValue());
                        break;
                    case "ramAvailableOid":
                        snmpOid.setRamAvailableOid(dictDO.getValue());
                        break;
                    case "ramSharedOid":
                        snmpOid.setRamSharedOid(dictDO.getValue());
                        break;
                    case "ramBufferOid":
                        snmpOid.setRamBufferOid(dictDO.getValue());
                        break;
                    case "ramCachedOid":
                        snmpOid.setRamCachedOid(dictDO.getValue());
                        break;
                    case "cpuProcessorLoadOid":
                        snmpOid.setCpuProcessorLoadOid(dictDO.getValue());
                        break;
                    case "diskPathOid":
                        snmpOid.setDiskPathOid(dictDO.getValue());
                        break;
                    case "diskTypeOid":
                        snmpOid.setDiskTypeOid(dictDO.getValue());
                        break;
                    case "diskAllocationUnitsOid":
                        snmpOid.setDiskAllocationUnitsOid(dictDO.getValue());
                        break;
                    case "diskStorageSizeOid":
                        snmpOid.setDiskStorageSizeOid(dictDO.getValue());
                        break;
                    case "diskUsedOid":
                        snmpOid.setDiskUsedOid(dictDO.getValue());
                        break;
                    case "mainDiskUsedOid":
                        snmpOid.setMainDiskUsedOid(dictDO.getValue());
                        break;
                    case "sendOid":
                        snmpOid.setSendOid(dictDO.getValue());
                        break;
                    case "receiveOid":
                        snmpOid.setReceiveOid(dictDO.getValue());
                        break;
                    case "cpuIdleOId":
                        snmpOid.setCpuIdleOId(dictDO.getValue());
                        break;
                }
            }
            return snmpOid;
        } else {
            return null;
        }
    }

    //統一判斷snmp的返回數據是否有誤
    public static Boolean ifListTrue(List<Map<String, String>> list, String oid) {
        return list != null && list.size() > 0 && list.get(0).get(oid) != null && !list.get(0).get(oid).equals("noSuchInstance") && !list.get(0).get(oid).equals("noSuchObject");
    }


    public static String getChinese(String octetString) {    //snmp4j遇到中文直接轉成16進制字符串
        try {
            String[] temps = octetString.split(":");
            byte[] bs = new byte[temps.length];
            for (int i = 0; i < temps.length; i++)
                bs[i] = (byte) Integer.parseInt(temps[i], 16);
            return new String(bs, "GB2312");
        } catch (Exception e) {
            return octetString;
        }
    }


    public static void main(String[] args) {

        String memTotal = ".1.3.6.1.4.1.2021.4.5.0";
        String memAvailable = ".1.3.6.1.4.1.2021.4.6.0";
        String memShared = ".1.3.6.1.4.1.2021.4.13.0";
        String memBuffer = ".1.3.6.1.4.1.2021.4.14.0";
        String memCached = ".1.3.6.1.4.1.2021.4.15.0";
        List<Map<String, String>> memTotalList = SnmpUtils.snmpGet("", "public", "161", memTotal);
        List<Map<String, String>> memAvailableList = SnmpUtils.snmpGet("", "public", "161", memAvailable);
        List<Map<String, String>> memSharedList = SnmpUtils.snmpGet("", "public", "161", memShared);
        List<Map<String, String>> memBufferList = SnmpUtils.snmpGet("", "public", "161", memBuffer);
        List<Map<String, String>> memCachedList = SnmpUtils.snmpGet("", "public", "161", memCached);

        Long memTotalTemp = Long.parseLong(memTotalList.get(0).get(memTotal));
        Long memAvailableTemp = Long.parseLong(memAvailableList.get(0).get(memAvailable));
        Long memSharedTemp = Long.parseLong(memSharedList.get(0).get(memShared));
        Long memBufferTemp = Long.parseLong(memBufferList.get(0).get(memBuffer));
        Long memCachedTemp = Long.parseLong(memCachedList.get(0).get(memCached));

        if (memSharedTemp + memAvailableTemp + memCachedTemp > memTotalTemp) {
            Long temp = memTotalTemp - memAvailableTemp - memBufferTemp - memCachedTemp + memSharedTemp;
            String used = new DecimalFormat("0").format(temp * 100 / memTotalTemp);
            System.out.println(temp);
            System.out.println(memTotalTemp);
            System.out.println(used);
            System.out.println("111");
        } else {
            Long temp = memTotalTemp - memAvailableTemp - memBufferTemp - memCachedTemp;
            String used = new DecimalFormat("0").format(temp * 100 / memTotalTemp);
            System.out.println(temp);
            System.out.println(memTotalTemp);
            System.out.println(used);
            System.out.println("222");
        }
    }
}


3.windows監測所使用的oid

參考:https://blog.csdn.net/liuhuango123/article/details/52253953

4.linux監測所使用的oid

參考:https://blog.csdn.net/apple_llb/article/details/50494787

5.根據業務需求採用所需的oid通過調用util工具類裏面的snmpGet及snmpWalk方法即可

例子:獲取windows磁盤總大小

public static void main(String[] args) {

        String memTotal = ".1.3.6.1.4.1.2021.4.5.0";
        List<Map<String, String>> memTotalList = SnmpUtils.snmpGet("ip", "public", "161", memTotal);
        Long memTotalTemp = Long.parseLong(memTotalList.get(0).get(memTotal));
        System.out.println(memTotalTemp);
            
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章