Dies ist der Artikel am 11. Tag von NetOpsCoding AdventCalender.
Dieses Mal werde ich ein Verkehrsdiagramm implementieren, das fast immer bestätigt wird, wenn Netzwerkoperationen mit einer Technologie namens * WebSocket * ausgeführt werden. Die Demo und der Quellcode werden am Ende eingefügt.
** Diese Implementierungsmethode wird unter Bezugnahme auf das von @yuyarin für die Überwachung in [Cedec2015] verwendete Tool (http://cedec.cesa.or.jp/2015/) implementiert. ** **.
Um ein solches Problem zu lösen, werde ich ein Diagramm erstellen, das * visuell leicht zu verstehen ist und kurzfristige Verkehrsänderungen in Echtzeit erfassen kann.
WebSocket ist eine relativ neue Technologie. Sie können den Zeitpunkt des Sendens und Empfangens von Daten sowie die Kommunikationsmethode frei bestimmen. Sobald Sie eine Sitzung gepostet haben, können Sie problemlos Daten in beide Richtungen übertragen.
Das Zeichnen von Graphen kann mit beiden erreicht werden, aber ich werde trotzdem versuchen, WebSocket zu verwenden, das auf andere Tool-Implementierungen anwendbar zu sein scheint! !! Wie auch immer, lass es uns sofort benutzen!
Für die Anzeige im Web ist eine Plattform wie Nginx oder Apache erforderlich. Dieser Demo-Server verwendet Nginx. Außerdem wird diesmal 8080 für die WS-Kommunikation verwendet.
Die WebSocket-Bibliothek verwendet tornado. Es gibt Gevent-WebSocket, ws4py usw., aber Tornado kam am meisten zu mir.
Obwohl HighCharts als Diagrammzeichnungswerkzeug verwendet wird, gibt es kein Problem mit anderen Diagrammwerkzeugen, die dynamisch hinzugefügt werden können. Außerdem wird HightCharts mit Ausnahme des persönlichen Gebrauchs berechnet. Daher sollten diejenigen, die betroffen sind, andere Tools verwenden. ccchart wird empfohlen, da es reichlich Beispiele enthält.
Lassen Sie uns die Serverseite implementieren. Die serverseitige Implementierung von WebSocket ist nicht schwierig, wenn nur der Punkt der "asynchronen Verarbeitung" unterdrückt wird. Wenn es einen bestimmten URI abhört und der Client verbunden ist, können Daten frei miteinander ausgetauscht werden, sodass das Ergebnis der Erfassung von SNMP gesendet werden kann. SNMP wird durch Ausführen von Befehlen per Unterprozess erfasst und die Ergebnisse werden mit regulären Ausdrücken extrahiert. Außerdem wird diesmal die OID angegeben, die den Zähler der Netzwerkkarte des eigenen Servers betrachtet.
Nachdem Sie den folgenden Code implementiert haben, führen Sie ihn einfach mit dem Befehl python aus, um den Aufbau des WebSocket-Servers abzuschließen!
ws_traffic_server.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.options import define, options ,parse_command_line
from datetime import datetime
import shlex, subprocess , time ,re , json ,threading
SLEEP_TIME = 20 #Intervall, um SNMP zu erhalten
COMMUNITY = 'dev'
IP = '127.0.0.1'
IFMIB_OID = '1.3.6.1.2.1.31.1.1.1'
snmp_command_in = 'snmpget -v 2c -c %s %s %s.6.2'%(COMMUNITY,IP,IFMIB_OID)
snmp_command_out = 'snmpget -v 2c -c %s %s %s.10.2'%(COMMUNITY,IP,IFMIB_OID)
#Geben Sie den Port an, den WebSocket abhört
define("port", default = 8080,type = int)
class SendWebSocket(tornado.websocket.WebSocketHandler):
#Ereignis, das aufgerufen wird, wenn eine Verbindung gesichert ist
def open(self):
print 'Session Opened. IP:' + self.request.remote_ip
#Ereignisse, wenn ein Trennungsereignis auftritt, z. B. wenn der Browser geschlossen wird
def on_close(self):
print "Session closed"
#Ein Ereignis, das aufgerufen wird, wenn eine Nachricht vom Client gesendet wird
def on_message(self, message):
if message == 'hello':
pre_counter_in = int(self.exe_snmp(snmp_command_in))
pre_counter_out = int(self.exe_snmp(snmp_command_out))
#Zeit auf WebSocket.Timer kann nicht verwendet werden. Reproduzieren Sie die Verzögerung mit der folgenden Variablen CallBack
#SLEE_Starten Sie die Kommunikationsverarbeitung mit SNMP in der zweiten Hälfte nach TIME Sekunden
tornado.ioloop.IOLoop.instance().call_later(SLEEP_TIME,self.snmp_second_half,{'in_counter':pre_counter_in,'out_counter':pre_counter_out})
#SLEEP_Holen Sie sich SNMP nach TIME Sekunden
def snmp_second_half(self,pre_counters):
result = {}
pos_counter_in = int(self.exe_snmp(snmp_command_in))
pos_counter_out = int(self.exe_snmp(snmp_command_out))
#Verkehrsberechnung aus der Zählerdifferenz von der angegebenen Anzahl von Sekunden
traffic_in = (pos_counter_in - pre_counters['in_counter']) / SLEEP_TIME
traffic_out = (pos_counter_out - pre_counters['out_counter']) / SLEEP_TIME
#Senden Sie JSON-konvertierte Verkehrsdaten an einen Webclient
try:
result.update({'traffic_in' : traffic_in , 'traffic_out' : traffic_out})
result.update({'timestamp' : time.mktime(datetime.now().timetuple())})
self.write_message(json.dumps(result))
except:
print "Client is already disconnectted."
#Gibt nur den Wert des SNMP-Ausführungsergebnisses zurück
#e.g. [IF-MIB::ifHighSpeed.21 = Gauge32: 1000] -> [1000]
def exe_snmp(self,snmp_command):
split_command = shlex.split(snmp_command)
exec_output = subprocess.check_output(split_command)
r = re.compile("(.*)(: )(.*)")
snmp_result = r.match(exec_output).group(3)
return snmp_result
#Akzeptiert nur die Kommunikation von Hosts, die als nicht True angegeben sind
def check_origin(self, origin):
return True
#Wartet auf eine Verbindungsanforderung an WS am angegebenen URI
app = tornado.web.Application([
(r"/ws/ifmon/", SendWebSocket),
])
if __name__ == "__main__":
parse_command_line()
app.listen(options.port)
mainloop = tornado.ioloop.IOLoop.instance()
mainloop.start() #Starten Sie WebSocket Server
Was hier leicht zu verstehen ist, ist der Prozess, den Datenverkehr von Netzwerkgeräten von SNMP zu erfassen und zu berechnen.
Verkehrsberechnung durch SNMP
(Aktueller IFcounter --IFcounter nach n Sekunden) / n
Da es nicht berechnet werden kann, ohne mehrere zehn Sekunden zu warten, muss das Programm auch n Sekunden warten.
Time.sleep ()
in der Standardbibliothek kann jedoch nicht für asynchrone Kommunikation wie WebSocket verwendet werden. Da der gesamte Prozess in den Ruhezustand versetzt wird, sind auch andere Betrachter betroffen.
Dies wurde durch eine Funktion namens "IOLoop.call_later ()" gelöst, die im Tornado bereitgestellt wird und nach einer Verzögerung zurückrufen kann.
Ich habe das Gefühl, dass das Programm mit Gewalt erstellt wird, daher würde ich es begrüßen, wenn Sie einen Kommentar abgeben könnten, wenn Sie es richtig schreiben sollten.
Event | Zeitpunkt des Auftretens |
---|---|
onopen | Ereignis, das aufgerufen wird, wenn die Verbindung zum Server hergestellt ist |
onmessage | Ereignisse, die beim Empfang von Daten auftreten(Hauptort) |
onclose | Ereignis, das aufgerufen wird, wenn die Verbindung zum Server unterbrochen wird |
onerror | Ereignis, das aufgerufen wird, wenn ein Fehler auftritt |
Wenn die Verbindung zum Server hergestellt ist und das Ereignis "onopen" auftritt, wird ein Signal "Hallo" an den Server gesendet, um mit der Aufnahme von SNMP zu beginnen. Wenn Sie "Hallo" senden, reagiert die Serverseite und sendet die Verkehrsdaten. Wenn der Empfang von Daten vom Server erkannt wird, wird das Ereignis "onmessage" generiert, sodass der Graph innerhalb dieses Ereignisses gezeichnet wird. Wenn Sie eine Aktion abfangen, die das WebSocket trennt, z. B. das Schließen des Browsers, tritt das Ereignis "onclose" auf und die Kommunikation endet dort.
Da die Grafikeinstellungen lang sind, werde ich sie weglassen. Der relevante Teil der WebSocket-Verarbeitung wird wie folgt implementiert.
ws_client.js
var WS_URL = 'ws://www5445uo.sakura.ne.jp:8080/ws/ifmon/'
var init_ws_Traffic = function(){
var traffic_chart =Traffic_Chart('traffic_chart', {}); //Highhart-Graphkonstruktor
var ws = new WebSocket(WS_URL);
console.log('----- WebSocket Open -----')
ws.onopen = function() {//WS-Verbindungsaufbau
ws.send('hello');
};
ws.onerror = function(event){
$("p#error").text('Failed join to the server');
console.log('Connection faild....')
};
ws.onmessage = function(event) { //Verkehrsdatenverarbeitung
var data = JSON.parse(event.data);
var timestamp = data['timestamp']*1000 + 60 * 9 * 60 * 1000;
var value = data['traffic_in']
document.getElementById('traffic_in').innerHTML = convert_bps(value); //Als Text anzeigen
traffic_chart.series[0].addPoint([timestamp, value], true, true); //Das Hinzufügen des eingehenden Verkehrsdiagramms erfolgt hier
value = data['traffic_out']
document.getElementById('traffic_out').innerHTML = convert_bps(value);
traffic_chart.series[1].addPoint([timestamp, value], true, true);//Das Hinzufügen des ausgehenden Verkehrsdiagramms erfolgt hier
ws.send('hello'); //Nächste Verkehrsanfrage
};
ws.onclose = function () {
ws.send('close');
ws.close();
};
window.onbeforeunload = function () {
ws.send('close');
ws.close()
};
}
Die beiden oben genannten sind für die WebSocket-Kommunikation erforderlich. Wenn Sie überprüfen, was Sie tatsächlich auf dem Webbildschirm gemacht haben, sieht es so aus. Es ist eine Grafik ...!
Jetzt können Sie alle 10 Sekunden ein Verkehrsdiagramm für die Arbeit erhalten! Wenn Sie etwas Ähnliches machen und eine bessere Methode haben, lassen Sie es mich bitte wissen.
** Es gibt keine Live-Demo, da der Demo-Installationsserver verschwunden ist **
Der in der Demo verwendete Code ist unten aufgeführt. https://github.com/Mabuchin/wstraffic
Recommended Posts