从具有三个库的OID读取SNMP可以得出不同的执行时间

时间:2019-02-25 14:13:49

标签: python snmp pysnmp easysnmp gosnmp

我已经使用easysnmp来读取SNMP OID,但是由于pysnmp Python3 中不支持easysnmp架构,我现在选择了asyncio库。

所考虑的问题是,pysnmp的速度比其他库慢:

pysnmp:

from pysnmp.hlapi import *
import time

t = time.time()
iterator = getCmd(SnmpEngine(),
                  CommunityData('public'),
                  UdpTransportTarget(('192.168.1.120', 161)),
                  ContextData(),
                  ObjectType(ObjectIdentity("1.3.6.1.2.1.33.1.2.7.0")))

errorIndication, errorStatus, errorIndex, varBinds = next(iterator)

if errorIndication:  # SNMP engine errors
    print(errorIndication)
else:
    if errorStatus:  # SNMP agent errors
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            varBinds[int(errorIndex)-1] if errorIndex else '?'))
    else:
        for varBind in varBinds:  # SNMP response contents
            print(' = '.join([x.prettyPrint() for x in varBind]))


print(time.time() - t, 's') 

出局:

SNMPv2-SMI::mib-2.33.1.2.7.0 = 21
0.15317177772521973 s

easysnmp

from easysnmp import snmp_get
import time

if __name__ == '__main__':
    t = time.time()
    response = snmp_get(
        '1.3.6.1.2.1.33.1.2.7.0', hostname='192.168.1.120',
        community='public', version=1
    )
    print(response.value)
    print(time.time() - t, 's')

出局:

21
0.0063724517822265625 s

gosnmp

func elapsed(what string) func() {
    start := time.Now()
    fmt.Println("start")
    return func() {
        fmt.Printf("%s took %v\n", what, time.Since(start))
    }
}

func snmpRead() {
    g.Default.Target = "192.168.1.120"
    err := g.Default.Connect()
    if err != nil {
        log.Fatalf("Connect() err: %v", err)
    }
    defer g.Default.Conn.Close()

    oids := []string{"1.3.6.1.2.1.33.1.2.7.0"}
    result, err2 := g.Default.Get(oids) // Get() accepts up to g.MAX_OIDS
    if err2 != nil {
        log.Fatalf("Get() err: %v", err2)
    }

    for i, variable := range result.Variables {
        fmt.Printf("%d: oid: %s ", i, variable.Name)

        switch variable.Type {
        case g.OctetString:
            fmt.Printf("string: %s\n", string(variable.Value.([]byte)))
        default:
            fmt.Printf("number: %d\n", g.ToBigInt(variable.Value))
        }
    }
}

func main() {
    defer elapsed("snmp")()
    snmpRead()
}

出局:

start
0: oid: .1.3.6.1.2.1.33.1.2.7.0 number: 21
snmp took 3.668148ms

pysnmp快30倍


我需要在{em> Python3 中go-routine填充asyncio的异步性能。

那么,这是否意味着我应该从pysnmp迁移到gosnmp

1 个答案:

答案 0 :(得分:0)

请记住,相对于后续调用,第一次pysnmp调用可能要花费更多时间。由于延迟导入,索引编制,可能的MIB编译等。

因此,如果您的用例是从同一过程发出许多SNMP查询,我建议在测量所用时间时将其考虑在内。

另一件事是,最新的(未发布的)pysnmp通过低级SNMP例程引入了异步绑定,即不包括SNMP引擎及其涉及的所有繁琐的机器。

从签名角度来看,pysnmp.hlapi.v1arch.asyncio API的意图与pysnmp.hlapi.v3arch.asyncio非常相似,但是应该更快,但要以不支持SNMPv3为代价。如果需要,MIB支持仍然存在。

仅导入pysnmp.hlapi.asyncio时,您将有效地获得pysnmp.hlapi.v3arch.asyncio,因此要进入v1arch,您需要显式导入。

例如下面的脚本(在GitHub master pysnmp下运行)可能会更快:

import asyncio
from pysnmp.hlapi.v1arch.asyncio import *


@asyncio.coroutine
def run():
    snmpDispatcher = SnmpDispatcher()

    iterator = getCmd(
        snmpDispatcher,
        CommunityData('public'),
        UdpTransportTarget(('192.168.1.120', 161)),
        ('1.3.6.1.2.1.33.1.2.7.0', None)
    )

    errorIndication, errorStatus, errorIndex, varBinds = yield from iterator

    if errorIndication:
        print(errorIndication)

    elif errorStatus:
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
        )
              )
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))

    snmpDispatcher.transportDispatcher.closeDispatcher()


asyncio.get_event_loop().run_until_complete(run())