Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der gleichzeitigen Erfassung von SNMP-Informationen und Leistungstestmethoden durch Python

Detaillierte Erläuterung der gleichzeitigen Erfassung von SNMP-Informationen und Leistungstestmethoden durch Python

高洛峰
高洛峰Original
2017-03-28 09:28:143295Durchsuche

Dieser Artikel stellt hauptsächlich die detaillierte Erklärung der gleichzeitigen Erfassung von SNMP-Informationen und Leistungstests vor. Jetzt werde ich ihn mit Ihnen teilen und als Referenz verwenden. Folgen wir dem Editor und werfen wir einen Blick darauf

Python & SNMP

Es stehen viele vorgefertigte Bibliotheken zum Abrufen von SNMP-Informationen mit Python zur Verfügung, darunter die am häufigsten verwendeten eine ist

und

zwei Bibliotheken. Es gibt viele Beispiele für die beiden Bibliotheken im Internet. netsnmppysnmpDer Schwerpunkt dieses Artikels liegt auf dem gleichzeitigen Abrufen von SNMP-Daten, dh dem gleichzeitigen Abrufen von SNMP-Informationen von mehreren Computern.

netsnmp

Lassen Sie uns zuerst über netsnmp sprechen. Netsnmp von Python stammt tatsächlich aus dem Paket net-snmp.

Python ruft die Net-SNMP-Schnittstelle auf, um Daten über eine C-Datei abzurufen.

Daher können beim gleichzeitigen Erwerb mehrerer Maschinen keine Coroutinen verwendet werden, um diese zu erwerben. Da Coroutinen beim Abrufen von Daten verwendet werden, warten die Coroutinen immer darauf, dass die Net-SNMP-Schnittstelle Daten zurückgibt, anstatt die CPU auf andere Coroutinen umzuschalten, während sie auf Daten warten, wie bei der Verwendung von Sockets. Unter diesem Gesichtspunkt gibt es keinen Unterschied zwischen der Verwendung von Coroutinen und dem seriellen Abrufen.

Wie kann man also das Problem der gleichzeitigen Akquisition lösen? Sie können Threads und Multi-Thread-Erfassung verwenden (natürlich können Sie auch Multi-Prozess verwenden). Mehrere Threads rufen die Net-SNMP-Schnittstelle auf, um gleichzeitig Daten abzurufen, und dann wechselt die CPU kontinuierlich zwischen mehreren Threads. Nachdem ein Thread ein Ergebnis erhalten hat, kann er weiterhin die Schnittstelle aufrufen, um die nächsten SNMP-Daten abzurufen.

Hier habe ich ein Beispielprogramm geschrieben. Machen Sie zunächst alle Hosts und Oids zu Aufgaben, stellen Sie sie in die Warteschlange und starten Sie dann mehrere Threads, um die Erfassungsaufgabe auszuführen. Das Programmbeispiel lautet wie folgt:

Neben der Unterstützung von Get-Operationen unterstützt netsnmp auch Walk-Operationen, also das Durchlaufen eines Oids.
import threading
import time
import netsnmp
import Queue
start_time = time.time()
hosts = ["192.20.150.109", "192.20.150.110", "192.20.150.111", "192.20.150.112", "192.20.150.113", "192.20.150.114",
     "192.20.150.115", "192.20.150.116", "192.20.150.117", "192.20.150.118", "192.20.150.119", "192.20.150.120",
     "192.20.150.121", "192.20.80.148", "192.20.80.149", "192.20.96.59", "192.20.82.14", "192.20.82.15",
     "192.20.82.17", "192.20.82.19", "192.20.82.12", "192.20.80.139", "192.20.80.137", "192.20.80.136",
     "192.20.80.134", "192.20.80.133", "192.20.80.131", "192.20.80.130", "192.20.81.141", "192.20.81.140",
     "192.20.82.26", "192.20.82.28", "192.20.82.23", "192.20.82.21", "192.20.80.128", "192.20.80.127",
     "192.20.80.122", "192.20.81.159", "192.20.80.121", "192.20.80.124", "192.20.81.151", "192.20.80.118",
     "192.20.80.119", "192.20.80.113", "192.20.80.112", "192.20.80.116", "192.20.80.115", "192.20.78.62",
     "192.20.81.124", "192.20.81.125", "192.20.81.122", "192.20.81.121", "192.20.82.33", "192.20.82.31",
     "192.20.82.32", "192.20.82.30", "192.20.81.128", "192.20.82.39", "192.20.82.37", "192.20.82.35",
     "192.20.81.130", "192.20.80.200", "192.20.81.136", "192.20.81.137", "192.20.81.131", "192.20.81.133",
     "192.20.81.134", "192.20.82.43", "192.20.82.45", "192.20.82.41", "192.20.79.152", "192.20.79.155",
     "192.20.79.154", "192.25.76.235", "192.25.76.234", "192.25.76.233", "192.25.76.232", "192.25.76.231",
     "192.25.76.228", "192.25.20.96", "192.25.20.95", "192.25.20.94", "192.25.20.93", "192.24.163.14",
     "192.24.163.21", "192.24.163.29", "192.24.163.6", "192.18.136.22", "192.18.136.23", "192.24.193.2",
     "192.24.193.19", "192.24.193.18", "192.24.193.11", "192.20.157.132", "192.20.157.133", "192.24.212.232",
     "192.24.212.231", "192.24.212.230"]
oids = [".1.3.6.1.4.1.2021.11.9.0",".1.3.6.1.4.1.2021.11.10.0",".1.3.6.1.4.1.2021.11.11.0",".1.3.6.1.4.1.2021.10.1.3.1",
    ".1.3.6.1.4.1.2021.10.1.3.2",".1.3.6.1.4.1.2021.10.1.3.3",".1.3.6.1.4.1.2021.4.6.0",".1.3.6.1.4.1.2021.4.14.0",
    ".1.3.6.1.4.1.2021.4.15.0"]
myq = Queue.Queue()
rq = Queue.Queue()
#把host和oid组成任务
for host in hosts:
  for oid in oids:
    myq.put((host,oid))
def poll_one_host():
  while True:
    try:
      #死循环从队列中获取任务,直到队列任务为空
      host, oid = myq.get(block=False)
      session = netsnmp.Session(Version=2, DestHost=host, Community="cluster",Timeout=3000000,Retries=0)
      var_list = netsnmp.VarList()
      var_list.append(netsnmp.Varbind(oid))
      ret = session.get(var_list)
      rq.put((host, oid, ret, (time.time() - start_time)))
    except Queue.Empty:
      break
thread_arr = []
#开启多线程
num_thread = 50
for i in range(num_thread):
  t = threading.Thread(target=poll_one_host, kwargs={})
  t.setDaemon(True)
  t.start()
  thread_arr.append(t)
#等待任务执行完毕
for i in range(num_thread):
  thread_arr[i].join()
while True:
  try:
    info = rq.get(block=False)
    print info
  except Queue.Empty:
    print time.time() - start_time
    break

Sie müssen jedoch bei der Verwendung von Walk vorsichtig sein, um Probleme wie hohe Latenz zu vermeiden. Weitere Informationen finden Sie in einem früheren Blog zur Analyse von Problemen mit hoher Latenz in snmpwalk.

pysnmp

pysnmp ist eine Reihe von SNMP-Protokollbibliotheken, die in Python implementiert sind. Es selbst bietet Unterstützung für Asynchronität.

pysnmp selbst unterstützt nur die grundlegendsten get- und getnext-Befehle. Wenn Sie also walk verwenden möchten, müssen Sie es selbst implementieren.
import time
import Queue
from pysnmp.hlapi.asyncore import *
t = time.time()
myq = Queue.Queue()
#回调函数。在有数据返回时触发
def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
   myq.put((time.time()-t, varBinds))
hosts = ["192.20.150.109", "192.20.150.110", "192.20.150.111", "192.20.150.112", "192.20.150.113", "192.20.150.114",
     "192.20.150.115", "192.20.150.116", "192.20.150.117", "192.20.150.118", "192.20.150.119", "192.20.150.120",
     "192.20.150.121", "192.20.80.148", "192.20.80.149", "192.20.96.59", "192.20.82.14", "192.20.82.15",
     "192.20.82.17", "192.20.82.19", "192.20.82.12", "192.20.80.139", "192.20.80.137", "192.20.80.136",
     "192.20.80.134", "192.20.80.133", "192.20.80.131", "192.20.80.130", "192.20.81.141", "192.20.81.140",
     "192.20.82.26", "192.20.82.28", "192.20.82.23", "192.20.82.21", "192.20.80.128", "192.20.80.127",
     "192.20.80.122", "192.20.81.159", "192.20.80.121", "192.20.80.124", "192.20.81.151", "192.20.80.118",
     "192.20.80.119", "192.20.80.113", "192.20.80.112", "192.20.80.116", "192.20.80.115", "192.20.78.62",
     "192.20.81.124", "192.20.81.125", "192.20.81.122", "192.20.81.121", "192.20.82.33", "192.20.82.31",
     "192.20.82.32", "192.20.82.30", "192.20.81.128", "192.20.82.39", "192.20.82.37", "192.20.82.35",
     "192.20.81.130", "192.20.80.200", "192.20.81.136", "192.20.81.137", "192.20.81.131", "192.20.81.133",
     "192.20.81.134", "192.20.82.43", "192.20.82.45", "192.20.82.41", "192.20.79.152", "192.20.79.155",
     "192.20.79.154", "192.25.76.235", "192.25.76.234", "192.25.76.233", "192.25.76.232", "192.25.76.231",
     "192.25.76.228", "192.25.20.96", "192.25.20.95", "192.25.20.94", "192.25.20.93", "192.24.163.14",
     "192.24.163.21", "192.24.163.29", "192.24.163.6", "192.18.136.22", "192.18.136.23", "192.24.193.2",
     "192.24.193.19", "192.24.193.18", "192.24.193.11", "192.20.157.132", "192.20.157.133", "192.24.212.232",
     "192.24.212.231", "192.24.212.230"]
oids = [".1.3.6.1.4.1.2021.11.9.0",".1.3.6.1.4.1.2021.11.10.0",".1.3.6.1.4.1.2021.11.11.0",".1.3.6.1.4.1.2021.10.1.3.1",
    ".1.3.6.1.4.1.2021.10.1.3.2",".1.3.6.1.4.1.2021.10.1.3.3",".1.3.6.1.4.1.2021.4.6.0",".1.3.6.1.4.1.2021.4.14.0",
    ".1.3.6.1.4.1.2021.4.15.0"]
    
snmpEngine = SnmpEngine()
#添加任务
for oid in oids:
  for h in hosts:
    getCmd(snmpEngine,
      CommunityData('cluster'),
      UdpTransportTarget((h, 161), timeout=3, retries=0,),
      ContextData(),
      ObjectType(ObjectIdentity(oid)),
      cbFun=cbFun)
time1 = time.time() - t
#执行异步获取snmp
snmpEngine.transportDispatcher.runDispatcher()
#打印结果
while True:
  try:
    info = myq.get(block=False)
    print info
  except Queue.Empty:
    print time1
    print time.time() - t
    break

Leistungstest

In der gleichen Umgebung wurde der Leistungstest für beide durchgeführt. Die beiden sammelten 198 Hosts und 10 Oids.

Sie können sehen, dass die Erfassungsgeschwindigkeit von netsnmp mit der Anzahl der Threads zusammenhängt. Wenn die Anzahl der Threads bis zu einem bestimmten Grad zunimmt, wird die Erfassungszeit nicht mehr verkürzt. Denn auch das Öffnen von Threads kostet Zeit. Die vorhandenen Threads reichen zur Bearbeitung aus.
测试组 耗时(sec)
netsnmp(20线程) 6.252
netsnmp(50线程) 3.269
netsnmp(200线程) 3.265
pysnmp 4.812

Die Leistung von pysnmp ist etwas schlechter. Die detaillierte Analyse von pysnmp benötigt beim Hinzufügen von Aufgaben (beim Ausführen von getCmd) etwa 1,2 Sekunden und die anschließende Erfassung etwa 3,3 Sekunden.

Erhöhung der Anzahl von Oiden und Durchführung von Experimenten. Es gibt noch 198 Hosts und 42 Oids.

Es ist zu erkennen, dass sich die Kluft weiter vergrößert hat. Wenn genügend Threads vorhanden sind, ist netsnmp deutlich effizienter als pysnmp.
测试组 耗时(sec)
netsnmp(20线程) 30.935
netsnmp(50线程) 12.914
netsnmp(200线程) 4.044
pysnmp 11.043

Da beide die parallele Sammlung mehrerer Hosts unterstützen, ist netsnmp hinsichtlich der Benutzerfreundlichkeit einfacher und netsnmp unterstützt die Walk-Funktion. Dieser Artikel empfiehlt netsnmp.

Installation

netsnmp erfordert die Installation von net-snmp. Bei Centos ist es bequemer, Yum zu verwenden.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der gleichzeitigen Erfassung von SNMP-Informationen und Leistungstestmethoden durch Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn