[PYTHON] Ich habe versucht, den Datenverkehr mit WebSocket in Echtzeit zu beschreiben

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. ** **.

  1. Zuallererst = Kakteen, Zabbix, MRTG usw. sind als Werkzeuge zur Überwachung des Verkehrs bekannt. In den meisten Fällen beträgt das SNMP-Erfassungsintervall etwa 5 Minuten. Grundsätzlich bin ich mit der Bestätigung zufrieden, aber bei tatsächlichen Arbeiten wie dem Öffnen einer neuen Linie / dem Anpassen des Verkehrs möchte ich den Verkehr oft * in diesem Moment * sehen. Je nach Gerät kann der Echtzeitverkehr auf CLI-Basis überwacht werden. Mit CLI ist es jedoch schwierig, Änderungen im Status mehrerer Standorte zu bemerken, und gibt es eine Verzögerung bei der Erkennung von Anomalien?

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.

  1. Wie zeichnet man in Echtzeit im Web? = Es gibt zwei Hauptmethoden zum dynamischen Zeichnen eines Diagramms auf einem Webbildschirm.

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!

  1. Ausführungsumgebung =

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.

  1. Implementierung auf der WebSocket-Server-Seite =

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.

  1. Client-seitige Implementierung = Die Verarbeitung auf der Client-Seite wird von Javascript durchgeführt. Die Clientseite muss vier Ereignishandler kennen, um die vom Server gesendeten Verkehrsdaten verarbeiten zu können.
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. スクリーンショット 2015-12-11 1.19.25.png 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.

  1. Bonus (Demo und Quellcode) = Ich denke nicht, dass es gut ist, ohne das Gefühl, in Echtzeit aktualisiert zu werden Ich habe das, was ich gemacht habe, auf den Demo-Server hochgeladen. Es kann für eine begrenzte Zeit sein, aber bitte schauen Sie sich an, wie es aussieht. Wenn Sie etwa 20 Sekunden warten, ändert sich etwas.

** 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

  1. Schließlich = Ich habe vorgestellt, wie ein Verkehrsdiagramm für die Arbeit implementiert wird! Ich denke, dass es bequemer ist, wenn Sie es entsprechend Ihrem Zweck ändern, z. B. indem Sie es ermöglichen, den Datenverkehr mehrerer Geräte in einem Diagramm mit ein wenig Umschreiben darzustellen. Wenn Sie die Möglichkeit haben, es zu verwenden, versuchen Sie es bitte!

Recommended Posts

Ich habe versucht, den Datenverkehr mit WebSocket in Echtzeit zu beschreiben
Ich habe versucht, die Zeit und die Zeit der C-Sprache zu veranschaulichen
Ich habe versucht, das Bild mit OpenCV im "Skizzenstil" zu verarbeiten
Ich habe versucht, das Bild mit OpenCV im "Bleistift-Zeichenstil" zu verarbeiten
Ich habe versucht, das Problem von F02 zu lösen, wie man mit Python offline in Echtzeit schreibt
Ich habe versucht, die Daten mit Zwietracht zu speichern
Ich habe versucht, Keras in TFv1.1 zu integrieren
Wie man offline in Echtzeit schreibt Ich habe versucht, E11 mit Python zu lösen
Ich habe versucht, Gitarrenakkorde in Echtzeit mithilfe von maschinellem Lernen zu klassifizieren
Wie man offline in Echtzeit schreibt Ich habe versucht, E12 mit Python zu lösen
Ich habe versucht, die Sündenfunktion mit Chainer zu trainieren
Ich habe versucht, die in Python installierten Pakete grafisch darzustellen
Ich habe versucht, eine CSV-Datei mit Python zu berühren
Ich habe versucht, Soma Cube mit Python zu lösen
Ich habe versucht, die Pferde vorherzusagen, die mit LightGBM unter den Top 3 sein werden
Ich habe versucht, das Problem mit Python Vol.1 zu lösen
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich habe versucht zu simulieren, wie sich die Infektion mit Python ausbreitet
Ich habe versucht, die Emotionen des gesamten Romans "Wetterkind" zu analysieren
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Ich habe versucht, die Zugverspätungsinformationen mit LINE Notify zu benachrichtigen
Ich habe versucht, den in Pandas häufig verwendeten Code zusammenzufassen
Ich habe versucht, die Uhrzeit und das heutige Wetter anzuzeigen
Ich habe versucht, die im Geschäftsleben häufig verwendeten Befehle zusammenzufassen
Ich habe versucht, die Mail-Sendefunktion in Python zu implementieren
Ich kann mich mit Django 3 nicht auf der Admin-Seite anmelden
Ich habe versucht, den Immobilienpreis in Boston mit PyCaret vorherzusagen
Ich habe versucht, einen Artikel mit SQL Alchemy auf Wiki.js zu erstellen
Ich habe versucht, den Ball zu bewegen
Ich habe versucht, den Abschnitt zu schätzen.
(Python: OpenCV) Ich habe versucht, einen Wert auszugeben, der den Abstand zwischen Regionen angibt, während das Video in Echtzeit binärisiert wurde.
Ich habe versucht, zum Zeitpunkt der Bereitstellung mit Fabric und ChatWork Api automatisch in ChatWork zu posten
Ich habe auch versucht, die Funktionsmonade und die Zustandsmonade mit dem Generator in Python nachzuahmen
Ich schrieb einen Test in "Ich habe versucht, die Wahrscheinlichkeit eines Bingospiels mit Python zu simulieren".
Ich habe versucht, die Anfängerausgabe des Ameisenbuchs mit Python zu lösen
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe versucht, die Videowiedergabezeit anzuzeigen (OpenCV: Python-Version)
Ich habe am Wochenende versucht, mit Bitcoin Systre zu beginnen
Ich habe versucht, die Größe des logischen Volumes mit LVM zu erweitern
Vorerst möchte ich jede Datei mit ffmpeg konvertieren !!
Ich habe versucht, die Effizienz der täglichen Arbeit mit Python zu verbessern
Ich habe versucht, mich automatisch mit Selen bei Twitter anzumelden (RPA, Scraping)
Ich habe versucht, eine Funktion zu erstellen, um zu beurteilen, ob die wichtigsten Aktien der Welt Sommerzeit mit Python sind
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe versucht, den Befehl umask zusammenzufassen
Ich habe versucht, Permutation in Python zu implementieren
Ich habe zum ersten Mal Tensorflow ausprobiert
Ich habe versucht, AutoEncoder mit TensorFlow zu visualisieren
Ich versuchte das Weckwort zu erkennen
Ich habe versucht, mit Hy anzufangen
Ich habe versucht, PLSA in Python 2 zu implementieren
Ich habe zum ersten Mal versucht, mit DynamoDB und Step Functions eine serverlose Stapelverarbeitung zu erstellen
Ich habe versucht, die grafische Modellierung zusammenzufassen.
Ich habe versucht, ADALINE in Python zu implementieren
Ich habe versucht, das Umfangsverhältnis π probabilistisch abzuschätzen
Ich habe versucht, die COTOHA-API zu berühren
Ich habe versucht, PPO in Python zu implementieren
Ich habe versucht, CVAE mit PyTorch zu implementieren
Ich habe versucht, mit Pillow mit dem Bild zu spielen