Wie dupliziere ich den TCP-Verkehr zu einem oder mehreren Remote-Servern für Benchmarking-Zwecke?

30

Infrastruktur: Server im Rechenzentrum, Betriebssystem - Debian Squeeze, Webserver - Apache 2.2.16


Lage:

Der Live-Server wird täglich von unseren Kunden genutzt, sodass Anpassungen und Verbesserungen nicht getestet werden können. Daher möchten wir den eingehenden HTTP-Verkehr auf dem Live-Server in Echtzeit auf einen oder mehrere Remote-Server duplizieren. Der Datenverkehr muss an den lokalen Webserver (in diesem Fall Apache) UND an die Remote-Server weitergeleitet werden. Dadurch können wir Konfigurationen anpassen und anderen / aktualisierten Code auf den Remote-Servern für das Benchmarking und den Vergleich mit dem aktuellen Live-Server verwenden. Derzeit hört der Webserver ca. 60 zusätzliche Ports neben 80 und 443, aufgrund der Client-Struktur.


Frage: Wie kann diese Duplizierung auf einen oder mehrere Remote-Server implementiert werden?

Wir haben bereits versucht:

  • agnoster duplicator - dies würde eine offene Sitzung pro Port erfordern, was nicht zutreffend ist. ( https://github.com/agnoster/duplicator )
  • kklis proxy - leitet den Datenverkehr nur an den Remote-Server weiter, leitet ihn jedoch nicht an den lcoal-Webserver weiter. ( https://github.com/kklis/proxy )
  • iptables - DNAT leitet den Datenverkehr nur weiter, nicht jedoch an den lokalen Webserver
  • iptables - TEE dupliziert nur auf Servern im lokalen Netzwerk -> Die Server befinden sich aufgrund der Struktur des Datencenters nicht im selben Netzwerk
  • Vorgeschlagene Alternativen für die Frage "TCP-Datenverkehr mit einem Proxy duplizieren" bei stackoverflow ( https://stackoverflow.com/questions/7247668/duplicate-tcp-traffic-with-a-proxy ) waren nicht erfolgreich. Wie bereits erwähnt, funktioniert TEE nicht mit Remoteservern außerhalb des lokalen Netzwerks. teeproxy ist nicht mehr verfügbar ( https://github.com/chrislusf/tee-proxy ) und wir konnten es nirgendwo anders finden.
  • Wir haben eine zweite IP-Adresse hinzugefügt (die sich im selben Netzwerk befindet) und sie eth0: 0 zugewiesen (die primäre IP-Adresse wird eth0 zugewiesen). Kein Erfolg bei der Kombination dieser neuen IP- oder virtuellen Schnittstelle eth0: 0 mit der iptables-TEE-Funktion oder -Routen.
  • vorgeschlagenen Alternativen für die Frage „duplicate eingehender TCP - Datenverkehr auf debian squeeze“ (vorausgesetzt Doppelte eingehenden TCP - Datenverkehr auf Debian Squeeze ) waren erfolglos. Die cat | nc-Sitzungen (cat / tmp / prodpipe | nc 127.0.0.1 12345 und cat / tmp / testpipe | nc 127.0.0.1 23456) werden nach jeder Anforderung / Verbindung durch einen Client ohne Benachrichtigung oder Protokoll unterbrochen. Keepalive hat diese Situation nicht geändert. TCP-Pakete wurden nicht zum fernen System transportiert.
  • Zusätzliche Versuche mit mit verschiedenen Optionen von socat (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , https://stackoverflow.com/questions/9024227/duplicate-input- Unix-Stream-to-Multiple-TCP-Clients-using-Socat ) und ähnliche Tools waren nicht erfolgreich, da die bereitgestellte TEE-Funktion nur in FS schreibt.
  • Natürlich war es auch nicht erfolgreich, zu googeln und nach diesem "Problem" oder Setup zu suchen.

Hier gehen uns die Optionen aus.

Gibt es eine Methode zum Deaktivieren der Durchsetzung von "Server im lokalen Netzwerk" der TEE-Funktion bei Verwendung von IPTABLES?

Kann unser Ziel durch unterschiedliche Nutzung von IPTABLES oder Routes erreicht werden?

Kennen Sie ein anderes Werkzeug für diesen Zweck, das getestet wurde und für diese speziellen Umstände geeignet ist?

Gibt es eine andere Quelle für Tee-Proxy (die perfekt zu unseren Anforderungen passen würde, AFAIK)?


Vielen Dank im Voraus für Ihre Antworten.

----------

bearbeiten: 05.02.2014

Hier ist das Python-Skript, das so funktioniert, wie wir es brauchen:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

Die Kommentare zur Verwendung dieses Skripts:
Dieses Skript leitet eine Reihe von konfigurierten lokalen Ports an einen anderen lokalen und einen Remote-Socket-Server weiter.

Konfiguration:
Fügen Sie der Konfigurationsdatei port-forward.config die folgenden Zeilen mit Inhalten hinzu:

Fehlermeldungen werden in der Datei 'error.log' gespeichert.

Das Skript teilt die Parameter der Konfigurationsdatei auf:
Teilen Sie jede Konfigurationszeile mit Leerzeichen auf.
0: Lokaler Port zum Abhören
1: Lokaler Port zum Weiterleiten an
2: Remote-IP-Adresse des Zielservers
3: Remote-Port des Zielservers
und Rückgabe der Einstellungen

Sise
quelle
Ist der gesamte Datenverkehr HTTP?
Longneck
ja, der gesamte Datenverkehr ist HTTP.
Sise
1
btw. teeproxy ist hier verfügbar: github.com/chrislusf/teeproxy
Tombart
1
Eine andere Möglichkeit: github.com/ebowman/splitter Scala / Netty-based.
Rich K.

Antworten:

11

Es ist unmöglich. TCP ist ein Statefull-Protokoll. Der Endcomputer des Benutzers ist an jedem Verbindungsschritt beteiligt und antwortet niemals auf zwei separate Server, die versuchen, mit ihm zu kommunizieren. Alles, was Sie tun können, ist, alle http-Anfragen auf dem Webserver oder einem Proxy zu sammeln und sie erneut abzuspielen. Aber das gibt nicht und genaue Nebenläufigkeit oder Verkehrsbedingungen eines Live-Servers.

Kazimieras Aliulis
quelle
Das Duplizieren des TCP ist unmöglich - da stimme ich zu. Das Duplizieren des Layer 7-Datenverkehrs ist nicht der Fall. Sie können die Anforderungen vom Client erfassen und auf den anderen Servern wiedergeben. Einfache 1 Anfrage pro TCP-Sitzung Wiedergabe sollte ziemlich einfach sein. Anhaltende Verbindungen erfordern einige Überlegungen, wie Sie die zusätzlichen Anforderungen des Kunden zeitlich festlegen.
Evan Anderson
@ Kazimieras Aliulis: Es ist nicht erforderlich, mit zwei separaten Servern zu kommunizieren. Der Client kommuniziert mit dem Primärserver = dem Live-Server. Der Live-Server verarbeitet die Client-Anforderungen und beantwortet den Client. Neben der Verarbeitung und Beantwortung der Anfragen an den Client dupliziert der Primärserver die Anfragen an den zweiten Server = Testserver. Die Antworten des zweiten Servers an den Primärserver werden auf dem Primärserver verworfen / ignoriert und nicht an den Client weitergeleitet.
Sise
@Evan Anderson: Die Duplizierung auf HTTP-Ebene war auch unsere erste Idee, aber z. B. Apache Proxy oder ähnliche Tools oder Module ermöglichen es nicht, die Anforderungen lokal gleichzeitig zu verarbeiten und auf einen Remote-Host zu duplizieren. Wenn Sie eine andere Idee haben, beraten Sie bitte! :) Wir bevorzugen die Duplizierung gegenüber der Aufzeichnung und Wiedergabe, um sofortige Vergleichsergebnisse zu erzielen.
Sise
1
@Sise: Sie können versuchen, einen eigenen HTTP-Proxy zu schreiben, der den Datenverkehr an zwei Server weiterleitet. Es sollte ziemlich einfach sein, mit Python Twisted Framework twistedmatrix.com zu tun .
Kazimieras Aliulis
@ Kazimieras Aliulis: das ist definitiv eine Alternative! ich habe nie davon gehört. Aber das Auschecken zeigt, dass es perfekt zu unserem Zweck passen würde. Wir haben Python vorher nicht in Betracht gezogen, aber derzeit untersuchen wir das Twisted-Framework und die Möglichkeiten auch mit allgemeinem Python. Ich melde mich wieder, wenn es uns gelingt!
Sise
20

Nach allem, was Sie beschreiben, scheint GOR Ihren Bedürfnissen zu entsprechen. https://github.com/buger/gor/ "Wiedergabe des HTTP-Datenverkehrs in Echtzeit. Wiedergabe des Datenverkehrs von der Produktion über Staging- und Entwicklungsumgebungen." ?

Arthur Lutz
quelle
2
Dies ist genau das , wonach ich gesucht habe. Vielen Dank, Sie haben mich gerettet, genau dies in Go! :-)
chmac
Nginx hat Spiegelmodul. nginx.org/en/docs/http/ngx_http_mirror_module.html
Jimmy MG Lim
7

Teeproxy kann zum Replizieren des Datenverkehrs verwendet werden. Die Bedienung ist denkbar einfach:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a Produktionsserver
  • b Test Server

Wenn Sie einen HAproxy (mit roundrobin) vor Ihren Webserver stellen, können Sie 50% Ihrer Zugriffe einfach auf die Testseite umleiten:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)
Tombart
quelle
4

TCP ist ein statusbehaftetes Protokoll, das nicht dazu geeignet ist, Kopien der Pakete auf einem anderen Host zu senden, wie @KazimierasAliulis hervorhebt.

Es ist vernünftig, die Pakete auf der Ebene der TCP-Terminierung aufzunehmen und als neuen TCP-Stream weiterzuleiten. Das Duplikator-Tool , mit dem Sie verlinkt haben, scheint Ihre beste Wahl zu sein. Es fungiert als TCP-Proxy, sodass die TCP-Zustandsmaschine ordnungsgemäß funktioniert. Die Antworten Ihrer Testmaschinen werden einfach verworfen. Das klingt so, als würde es genau zu dem passen, was Sie wollen.

Mir ist nicht klar, warum Sie das Duplizierwerkzeug als inakzeptabel abgeschrieben haben. Sie müssen mehrere Instanzen des Tools ausführen, da es nur einen einzelnen Port überwacht. Vermutlich möchten Sie jedoch jeden dieser verschiedenen Überwachungsports an verschiedene Ports des Back-End-Systems weiterleiten. Wenn nicht, können Sie iptables DNAT verwenden, um alle Listening-Ports auf eine einzelne Listening-Kopie des Duplikator-Tools zu lenken.

Ich gehe davon aus, dass Sie Probleme mit dieser Testmethode in Bezug auf das Timing und den internen Anwendungsstatus haben werden, es sei denn, die Anwendungen, die Sie testen, sind einfach. Was Sie tun möchten, klingt täuschend einfach. Ich gehe davon aus, dass Sie viele Randfälle finden werden.

Evan Anderson
quelle
ja, sie haben vollkommen recht, das agnoster duplicator tool würde mit ausnahme der multi port situation unseren anforderungen entsprechen. Auch das Verwerfen der Antworten der Testmaschine ist vollbracht. Um unser Ziel zu erreichen, die reale Situation so genau wie möglich zu simulieren, können wir nicht alle Ports auf dem Live-Server auf einen einzigen Port auf dem Testcomputer bündeln. Verschiedene Ports werden verwendet, um Clientgeräte in verschiedene Kunden aufzuteilen. Dazu müssen wir 60-70 Sessions dieses Duplikator-Tools öffnen. Dies ist nicht sehr praktisch, wie Sie sich vorstellen können.
Sise
@Sise - Computer sind gut darin, mühsame Dinge zu tun. Ich denke, Sie könnten ein Skript schreiben, um Ihre Apache-Konfigurationen zu analysieren und die erforderlichen Befehlszeilen auszuspucken, um 60 bis 70 Instanzen des Duplizierertools auszuführen. Ich kann mir nicht vorstellen, dass das Duplizier-Tool sehr ressourcenintensiv ist, aber selbst wenn dies der Fall wäre, könnten Sie diese 60 bis 70 Instanzen auf einem anderen Computer ausführen und einige Netzwerk-Tricks ausführen, um den Datenverkehr dort hin zu leiten. Zumindest scheint mir das völlig praktisch und eine ziemlich unkomplizierte Art, damit umzugehen.
Evan Anderson
1

Ich versuche jedoch, etwas Ähnliches zu tun. Wenn Sie lediglich versuchen, die Auslastung eines Servers zu simulieren, würde ich mir so etwas wie ein Framework zum Testen der Auslastung ansehen. Ich habe locust.io in der Vergangenheit verwendet und es hat sehr gut funktioniert, um eine Auslastung auf einem Server zu simulieren. Auf diese Weise können Sie eine große Anzahl von Clients simulieren und mit der Konfiguration des Servers spielen, ohne den schmerzhaften Prozess der Weiterleitung von Datenverkehr an einen anderen Server durchlaufen zu müssen.

snowbirdSkiBum
quelle
0

Was "Wir möchten, dass der eingehende HTTP-Verkehr auf dem Live-Server in Echtzeit auf einen oder mehrere Remote-Server dupliziert wird", ist die oben nicht erwähnte Möglichkeit, einen Spiegelport auf dem Switch zu konfigurieren, mit dem er verbunden ist.

Bei Cisco Catalyst-Switches wird dies als SPAN bezeichnet (weitere Informationen hier ). In einer Cisco-Umgebung können Sie den gespiegelten Port sogar auf einem anderen Switch haben.

Der Zweck dieser Funktion ist jedoch die Analyse des Datenverkehrs, sodass sie unidirektional ist - Schlüsselwort im zitierten Text im ersten Absatz: eingehend . Ich glaube nicht, dass dieser Port Rückverkehr zulässt, und wenn ja, wie würden Sie mit doppeltem Rückverkehr umgehen? Das wird wahrscheinlich nur Verwüstung in Ihrem Netzwerk anrichten.

Also ... wollte nur eine Möglichkeit zu Ihrer Liste hinzufügen, aber mit dem Vorbehalt, dass es sich tatsächlich um eine Einbahnstraße handelt. Möglicherweise können Sie einen Hub an diesen Spiegelport anschließen und doppelte Serverantworten von einem lokalen Client-Simulator erhalten, der initiierte Sitzungen aufnimmt und antwortet. Dann duplizieren Sie eingehenden Datenverkehr auf Ihren doppelten Server wollen.

James
quelle
wir haben darüber nachgedacht, ich habe über die Alternative der Verwendung von SPAN gelesen. Da sich die Server jedoch in einem Rechenzentrum eines Drittanbieters befinden, haben wir nur begrenzte Möglichkeiten, Änderungen an der Hardware vorzunehmen. Ich habe bereits darum gebeten, 2 Server an einer zweiten NIC direkt anzuschließen. Diese Aktion in Kombination mit einem lokalen Netzwerk für nur diese 2 Server würde mir ermöglichen, IPTABLES mit TEE zu verwenden. Für diese Alternative müssten wir jedoch die externen IP-Adressen der Server ändern. Dies ist ein NoGo, da Clientgeräte für die Verbindung mit der festgelegten IP-Adresse konfiguriert sind.
Sise
0

Ich habe auch einen Reverse-Proxy / Load-Balancer für einen ähnlichen Zweck mit Node.js geschrieben (nur zum Spaß, zur Zeit nicht produktionsbereit).

https://github.com/losnir/ampel

Es ist sehr aufgeschlossen und unterstützt derzeit:

  • GET Verwenden der Round-Robin-Auswahl (1: 1)
  • POSTVerwenden der Anforderungsaufteilung Es gibt kein Konzept für "master" und "shadow" - das erste Backend, das antwortet, ist dasjenige, das die Client-Anfrage bearbeitet, und alle anderen Antworten werden verworfen.

Wenn jemand es nützlich findet, kann ich es verbessern, um flexibler zu sein.

losnir
quelle
Node.js ist eine sehr seltsame Wahl der Sprache für eine Anwendung wie diese, die eine sehr hohe Leistung erfordern wird. Ich bin mir nicht sicher, ob dies jemals produktionsreif sein wird.
Michael Hampton
Du liegst absolut richtig. Dies sollte nicht sehr performant sein - einfach zu schreiben (für mich). Ich denke es kommt auf die benötigte Belastung an. Ich konnte auf einer Low-End-Maschine (2 Kerne) etwas mehr als 1.000 U / s erreichen.
Losnir
0

Mein Unternehmen hatte eine ähnliche Anforderung, ein Paket zu klonen und an einen anderen Host zu senden (wir haben Marktdatensimulatoren ausgeführt und benötigten eine temporäre Lösung, die einen Marktdaten-TCP-Feed abhört, jedes Paket aufnimmt, aber auch einen Klon jedes Pakets an einen anderen Simulator sendet Server)

Diese Binärdatei läuft sehr gut. Sie ist eine Version von TCP Duplicator, wurde jedoch in Golang anstelle von jscript geschrieben, ist also viel schneller und funktioniert wie angekündigt.

https://github.com/mkevac/goduplicator

perfecto25
quelle
-1

Es gibt ein Tool, das von einem Mann aus einem chinesischen Unternehmen erstellt wurde, und vielleicht ist es das, was Sie brauchen: https://github.com/session-replay-tools/tcpcopy

Musikoder
quelle
2
Hallo und willkommen bei serverfault. Können Sie uns eine genauere Antwort geben? Was macht das Programm genau? Ist es in C geschrieben ...?
bgtvfr