>  기사  >  백엔드 개발  >  snmp 정보의 Python 동시 획득 및 성능 테스트 방법에 대한 자세한 설명

snmp 정보의 Python 동시 획득 및 성능 테스트 방법에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-03-28 09:28:143295검색

이번 글은 python snmp 정보 동시 획득과 성능 테스트에 대한 자세한 설명을 위주로 소개하고 있는데, 편집자는 꽤 괜찮다고 생각해서 공유해봅니다. 편집기를 따라가서 살펴보겠습니다

python & snmp

파이썬을 사용하여 snmp 정보를 얻을 수 있는 기성 라이브러리가 많이 있으며 그 중 가장 일반적으로 사용되는 라이브러리는 다음과 같습니다. 하나는netsnmp이고 pysnmp두 개의 도서관입니다. 인터넷에는 두 도서관의 예가 많이 있습니다.

이 글의 초점은 snmp 데이터를 동시에 얻는 방법, 즉 동시에 여러 컴퓨터에서 snmp 정보를 얻는 방법입니다.

netsnmp

먼저 netsnmp에 대해 이야기해 보겠습니다. Python의 netsnmp는 실제로 net-snmp 패키지에서 유래되었습니다.

Python은 net-snmp 인터페이스를 호출하여 c 파일을 통해 데이터를 얻습니다.

따라서 여러 머신을 동시에 획득하는 경우 코루틴을 사용하여 획득할 수 없습니다. 코루틴을 사용하기 때문에 데이터를 가져올 때 코루틴은 소켓을 사용할 때처럼 데이터를 기다리는 동안 CPU를 다른 코루틴으로 전환하는 대신 항상 net-snmp 인터페이스가 데이터를 반환할 때까지 기다립니다. 이러한 관점에서 보면 코루틴을 사용하는 것과 직렬 가져오기를 사용하는 것에는 차이가 없습니다.

그럼 동시획득 문제는 어떻게 해결할까요? 스레드와 멀티스레드 획득을 사용할 수 있습니다(물론 멀티프로세스도 사용할 수 있습니다). 여러 스레드가 net-snmp 인터페이스를 호출하여 동시에 데이터를 얻은 다음 CPU가 여러 스레드 간에 계속 전환합니다. 스레드가 결과를 얻은 후에는 계속해서 인터페이스를 호출하여 다음 snmp 데이터를 얻을 수 있습니다.

여기서 샘플 프로그램을 작성했습니다. 먼저 모든 호스트와 oid를 작업으로 만들어 대기열에 넣은 다음 여러 스레드를 시작하여 획득 작업을 실행합니다. 프로그램 샘플은 다음과 같습니다.

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

netsnmp는 get 작업을 지원하는 것 외에도 걷기 작업, 즉 oid 탐색도 지원합니다.

그러나 긴 지연 시간과 같은 문제를 피하기 위해 Walk를 사용할 때는 주의가 필요합니다. 자세한 내용은 snmpwalk의 높은 지연 시간 문제 분석에 대한 이전 블로그를 참조하세요.

pysnmp

pysnmp는 Python으로 구현된 snmp 프로토콜 라이브러리 세트입니다. 자체적으로 비동기식을 지원합니다.

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

pysnmp 자체는 가장 기본적인 get 및 getnext 명령만 지원하므로 walk를 사용하려면 직접 구현해야 합니다.

성능 테스트

같은 환경에서 두 제품 모두 성능 테스트를 진행했습니다. 두 사람은 198개의 호스트와 10개의 oid를 수집했습니다.

测试组 耗时(sec)
netsnmp(20线程) 6.252
netsnmp(50线程) 3.269
netsnmp(200线程) 3.265
pysnmp 4.812

netsnmp의 수집 속도는 스레드 수와 관련이 있음을 알 수 있습니다. 스레드 수가 어느 정도 증가하면 수집 시간이 더 이상 단축되지 않습니다. 스레드를 여는 데에도 시간이 걸리기 때문입니다. 기존 스레드는 처리하기에 충분합니다.

pysnmp의 성능이 약간 떨어집니다. pysnmp의 상세 분석에는 작업 추가 시(getCmd 실행 시) 약 1.2초가 소요되며, 이후 수집에는 약 3.3초가 소요됩니다.

오이드 수를 늘리고 실험을 진행합니다. 여전히 198개의 호스트와 42개의 oid가 있습니다.

测试组 耗时(sec)
netsnmp(20线程) 30.935
netsnmp(50线程) 12.914
netsnmp(200线程) 4.044
pysnmp 11.043

격차가 더욱 벌어졌다고 볼 수 있다. 스레드가 충분하면 netsnmp가 pysnmp보다 훨씬 더 효율적입니다.

둘 다 여러 호스트의 병렬 수집을 지원하기 때문에 netsnmp는 사용 편의성 측면에서 더 간단하고 netsnmp는 걷기 기능을 지원합니다. 이 기사에서는 netsnmp를 권장합니다.

설치netsnmp를 사용하려면 net-snmp 설치가 필요합니다. 센토스라면 yum을 사용하는 것이 더 편리할 것입니다.

위 내용은 snmp 정보의 Python 동시 획득 및 성능 테스트 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.