抓取多个单一和分支 OID 的最有效方法是什么?

问题描述 投票:0回答:2

我总是处于最大速度和最小资源消耗之间的战争,所以我的目标是找到速度和资源消耗的最佳组合。
对于每个 snmp 设备,我想扫描几个分支下的 oid。
每个分支下都有动态数量的 oid,所以我不知道我需要什么特定的 oid,我只知道我需要一个分支下的所有 oid。
我有一些仅支持 SNMPv1 的设备,因此对于这些设备,我编写了与 SNMPv1 兼容的代码。
对于其余设备,我使用 SNMPv2。

SNMPv1

假设我有两个 OID,我想遍历它们的

branch('1.3.6.1.2.1.4' and '1.3.6.1.2.1.6')

我所说的分支 OID 是指分支下的所有 OID。
我有以下代码:

cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.asyncNextCmd(
  cmdgen.CommunityData('public', mpModel=1),
  cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
  (str('1.3.6.1.2.1.4'),str('1.3.6.1.2.1.6'),),
  (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1), cmdgen.UdpTransportTarget(('192.168.0.101', 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

这很有效,但唯一的问题是我只能一次停止所有步行,因此我不能单独停止每条步行,所以一旦最长的步行结束,所有步行都会结束。
显然这是低效的。
我还可以为分支 OID 写 2

asyncNextCmd

cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.asyncNextCmd(
        cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
        (str('1.3.6.1.2.1.4'),),
        (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161))))) 
cmdGen.asyncNextCmd(
        cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
        (str('1.3.6.1.2.1.6'),),
        (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

我不太了解 SNMP,但我认为第二个代码有一些缺点。
例如,在某些客户端上,我有数百个 SNMP 设备,因此我同时为每个网络设备打开一个

asyncCmd

这导致大量设备无响应且 CPU 使用率过高。

SNMPv2

我还想尝试了解批量工作原理以及是否可以使用它来提高我的代码效率。
假设我有 2 个分支想要步行。
1.3.6.1.2.1.4.20 有 5 个 oid,1.3.6.1.2.1.4.21 有 39 个 oid。
我得到了两个分支中的所有值,但我也得到了比我想要的更多的值。
我获得的值的数量始终是具有最高 oid 数量的分支乘以我拥有的分支数量。
例如 oid 最多的分支有 39 个 oid,分支数量为 2,所以 39*2=78,这意味着 getBulk 将返回 78 个 oid。
我希望 getBulk 返回每个分支的所有分支 oid,而不是更多,所以在我的例子中,我想要 44 个 oid(39+5 = 44)。
这是我的代码:

cmdGen = cmdgen.CommandGenerator()

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.bulkCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
  0, 1,
  '1.3.6.1.2.1.4.21', '1.3.6.1.2.1.4.20'
)

if errorIndication:
  print errorIndication
elif errorStatus:
  print '%s at %s\n' % (
    errorStatus.prettyPrint(),
    errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
  )
else:
  for varBindTableRow in varBindTable:
    for name, val in varBindTableRow:
      print str(name.prettyPrint()) + ' = ' + str(val.prettyPrint())

那么,为 SNMPv1 和 SNMPv2 抓取多个分支 OID 的最有效方法是什么?

python cpu snmp pysnmp
2个回答
1
投票

首先要认识到的是,您无法指示 SNMP 代理返回您精确的“分支”。 SNMP(协议级别)不支持此类操作。管理者可以控制请求哪些 OID 以及何时停止。代理可以返回精确的单个 OID (GET) 或下一个 OID (GETNEXT/GETBULK) 或一次返回下一个 OID 的大概数量 (GETBULK)。

如果您有动态 OID,您无法可靠地预测在任何给定时刻有多少个 OID。因此,我认为您无法在单个 SNMP 操作中或多或少地严格获取分支 OID。

话虽如此,我认为你应该尽可能尝试使用 GETBULK。瞄准最大预期 OID 数量,在一次 GETBULK 操作中抓取它们。但检查您的代码,您确实获得了所有内容(代理可能不会一次返回所请求数量的 OID)。

对于您正在使用的 pysnmp API,要停止其 GETBULK/GETNEXT 迭代,您应该从回调函数中返回 True。您可以分析从代理那里获得的 OID,并在它们超出您感兴趣的分支时返回 True。这将终止一个分支检索,其余分支将继续运行。

针对不同 OID 向同一 SNMP 代理发送多个并行查询的设计显然效率低得多。


0
投票

您想要

bulkCmd
,如

所述

https://docs.lextudio.com/pysnmp/

它将以更少和更大的块从网络设备返回数据。

© www.soinside.com 2019 - 2024. All rights reserved.