Frage Wie du TCP-Verkehr für Benchmarking-Zwecke auf einen oder mehrere Remote-Server duplizieren kannst?


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


Situation:

Der Live-Server wird täglich von unseren Kunden genutzt, so dass Anpassungen und Verbesserungen nicht möglich sind. Daher möchten wir den eingehenden HTTP-Verkehr auf dem Live-Server in Echtzeit auf einen oder mehrere Remote-Server kopieren. Der Datenverkehr muss an den lokalen Webserver (in diesem Fall Apache) UND an den / die entfernten Server übergeben werden. Dadurch können wir Konfigurationen anpassen und auf dem / den Remote-Server / s verschiedene / aktualisierten Code zum Benchmarking und Vergleich mit dem aktuellen Live-Server verwenden. Momentan hört der Webserver ca. 60 zusätzliche Ports außer 80 und 443, wegen der Client-Struktur.


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

Wir haben es schon versucht:

  • Agnoster Duplikator - dies würde eine offene Sitzung pro Port erfordern, die nicht anwendbar ist. (https://github.com/agnoster/duplikator)
  • 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, übergibt ihn jedoch nicht an den lokalen Webserver
  • iptables - TEE wird nur auf Servern im lokalen Netzwerk dupliziert -> Die Server befinden sich aufgrund der Struktur des Datencenters nicht im selben Netzwerk
  • vorgeschlagene Alternativen für die Frage "duplizieren tcp-Verkehr mit einem Proxy" bei stackoverflow (https://stackoverflow.com/questions/7247668/duplicate-tcp-traffic-with-a-proxy) waren erfolglos. Wie erwähnt, funktioniert TEE nicht mit Remote-Servern 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 (die sich im selben Netzwerk befindet) hinzugefügt und sie eth0 zugewiesen: 0 (primäre IP-Adresse ist eth0 zugewiesen). Kein Erfolg mit der Kombination dieser neuen IP oder virtuellen Schnittstelle eth0: 0 mit iptables TEE-Funktion oder Routen.
  • vorgeschlagene Alternativen für die Frage "Duplizieren des eingehenden TCP-Verkehrs auf Debian-Squeeze" (Duplizieren Sie eingehenden TCP-Verkehr unter 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 Anfrage / Verbindung von einem Client ohne vorherige Ankündigung oder Protokoll unterbrochen. Keepalive hat diese Situation nicht verändert. TCP-Pakete wurden nicht zum Remote-System transportiert.
  • Zusätzliche Versuche 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 schreiben wird.
  • Natürlich war das Suchen nach diesem "Problem" oder Setup auch nicht erfolgreich.

Uns gehen die Optionen aus.

Gibt es eine Methode zum Deaktivieren der Durchsetzung von "Server im lokalen Netzwerk" der TEE-Funktion bei der 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 unter diesen besonderen Umständen funktioniert?

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


Vielen Dank im Voraus für Ihre Antworten.

----------

edit: 05.02.2014

Hier ist das Python-Skript, das so funktionieren würde, 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 Anzahl von konfigurierten lokalen Ports an einen anderen lokalen und einen entfernten Socket-Server weiter.

Aufbau:
Fügen Sie der Datei config port-forward.config Zeilen mit folgendem Inhalt hinzu:

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

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


26
2018-01-29 15:02


Ursprung


Ist der gesamte Traffic HTTP? - longneck
Ja, der gesamte Verkehr ist HTTP. - Sise
übrigens. teeproxy ist hier verfügbar: github.com/chrislusf/teeproxy - Tombart
Andere Möglichkeit: github.com/ebowman/splitter Scala / Netty-basiert. - Rich K.


Antworten:


Es ist unmöglich. TCP ist ein statusfähiges Protokoll. Der Benutzercomputer 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 wird nicht geben und genaue Nebenläufigkeit oder Verkehrsbedingungen eines Live-Servers.


10
2018-01-29 15:19



Duplizieren der TCP ist unmöglich - ich stimme dem zu. Duplizieren der Schicht 7-Verkehr ist nicht. Sie können die Anforderungen vom Client erfassen und sie auf den anderen Servern wiedergeben. Einfache 1 Anfrage pro TCP-Session-Wiedergabe sollte ziemlich einfach sein. Dauerhafte Verbindungen erfordern einige Überlegungen, wie Sie die zusätzlichen Anforderungen des Clients zeitlich festlegen. - Evan Anderson
@Kazimieras Aliulis: Es ist nicht erforderlich, mit zwei separaten Servern zu kommunizieren. Der Client kommuniziert mit dem primären Server = dem Live-Server. Der Live-Server verarbeitet die Client-Anfragen und beantwortet den Client. Neben der Verarbeitung und Beantwortung des Clients vervielfältigt der primäre Server die Anfragen an den zweiten Server = Testserver. Die Antworten vom zweiten Server zum primären Server werden auf dem primären Server verworfen / ignoriert und nicht an den Client weitergeleitet. - Sise
@Evan Anderson: Duplizierung auf HTTP-Ebene war unsere erste Idee, aber z. Apache-Proxy oder ähnliche Tools oder Module erlauben nicht gleichzeitig die Verarbeitung der Anfragen lokal und duplizieren sie zu einem entfernten Host. Wenn Sie eine andere Idee haben, bitte Beratung! :) Wir bevorzugen Duplizierung gegenüber Aufnahme und Wiedergabe, um sofortige Vergleichsergebnisse zu erhalten. - Sise
@Sise: Sie könnten versuchen, Ihren eigenen HTTP-Proxy zu schreiben, der den Datenverkehr an zwei Server weiterleitet. Es sollte ziemlich einfach mit Python Twisted Framework zu tun sein twistedmatrix.com. - Kazimieras Aliulis
@Kazimieras Aliulis: das ist definitiv eine Alternative! ich habe nie davon gehört. Aber wenn wir es überprüfen, zeigt sich, dass es perfekt zu unserem Zweck passt. Wir haben Python vorher nicht in Betracht gezogen, aber im Moment betrachten wir das Twisted-Framework und die Möglichkeiten mit General Python. Ich werde berichten, wenn wir Erfolg haben! - Sise


Von dem, was Sie beschreiben, scheint GOR Ihre Bedürfnisse zu erfüllen. https://github.com/buger/gor/ "HTTP-Traffic-Wiedergabe in Echtzeit. Wiedergabe von Traffic von Produktion zu Staging und Dev-Environments." ?


19
2017-09-03 13:43



Das ist genau Was ich gesucht habe, vielen Dank, du hast mich gerettet, genau das zu schreiben, in Go! :-) - chmac


Teeproxy könnte verwendet werden, um Verkehr zu replizieren. Die Verwendung ist sehr einfach:

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

Wenn Sie ein HAproxy (mit roundrobin) Vor Ihrem Webserver können Sie 50% Ihres Traffics auf die Testseite umleiten:

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

5
2018-02-16 08:44





Da TCP ein Stateful-Protokoll ist, ist es nicht einfach, Kopien der Pakete auf einen anderen Host zu übertragen, wie @KazimierasAliulis hervorhebt.

Es ist sinnvoll, die Pakete auf der TCP-Terminierungsschicht aufzuheben und sie als neuen TCP-Stream weiterzuleiten. Das Kopierwerkzeug Sie verlinkt zu aussieht wie Ihre beste Wette. Es arbeitet als ein TCP-Proxy, der es der TCP-Statusmaschine ermöglicht, ordnungsgemäß zu arbeiten. Die Antworten Ihrer Testmaschinen werden einfach verworfen. Das hört sich so an, als ob es genau das Richtige für Sie ist.

Es ist mir unklar, warum Sie das Duplikator-Tool als inakzeptabel abgeschrieben haben. Sie müssen mehrere Instanzen des Tools ausführen, da es nur einen einzelnen Port überwacht, aber vermutlich möchten Sie diese verschiedenen empfangenden Ports an verschiedene Ports im Back-End-System weiterleiten. Wenn nicht, könnten Sie iptables DNAT verwenden, um alle Listening-Ports zu einer einzigen Wiedergabekopie des Duplikatortools zu leiten.

Wenn die Anwendungen, die Sie testen, nicht einfach sind, erwarte ich, dass Sie Probleme mit dieser Testmethodik in Bezug auf das Timing und den internen Anwendungsstatus haben werden. Was Sie tun möchten, klingt täuschend einfach - ich erwarte, dass Sie viele Edge Cases finden werden.


4
2018-01-29 17:52



Ja, Sie haben völlig Recht, das Agnoster-Duplikator-Tool würde unseren Anforderungen entsprechen, mit Ausnahme der Multi-Port-Situation. Auch das Verwerfen der Antworten der Testmaschine ist erfüllt. Um unser Ziel zu erreichen, die reale / Live-Situation so genau wie möglich zu simulieren, können wir nicht alle Ports des Live-Servers zu einem einzigen Port auf der Testmaschine bündeln. Verschiedene Ports werden verwendet, um Clientgeräte in verschiedene Kunden zu unterteilen. Dabei müssen wir 60-70 Sitzungen dieses Duplikator-Tools öffnen. Dies ist nicht sehr praktisch, wie Sie sich vorstellen können. - Sise
@Sise - Computer sind gut darin, langweilige Dinge zu tun. Ich denke, Sie könnten ein Skript schreiben, um Ihre Apache-Konfigurationen zu analysieren und die notwendigen Befehlszeilen auszuspucken, um 60 - 70 Instanzen des Duplikator-Tools auszuführen. Ich kann mir nicht vorstellen, dass das Duplikator-Tool sehr ressourcenintensiv ist, aber selbst wenn es so wäre, könnten Sie diese 60-70-Instanzen auf einem anderen Computer ausführen und einige Netzwerk-Tricks ausführen, um den Datenverkehr dorthin zu bringen. Für mich zumindest scheint das völlig praktisch zu sein und ein ziemlich unkomplizierter Umgang damit. - Evan Anderson


Ich versuche, etwas Ähnliches zu tun, aber wenn Sie nur versuchen, die Last auf einem Server zu simulieren, würde ich mir etwas wie ein Lasttest-Framework ansehen. Ich habe in der Vergangenheit locust.io benutzt und es hat wirklich gut funktioniert, um eine Last auf einem Server zu simulieren. Das sollte Ihnen ermöglichen, eine große Anzahl von Clients zu simulieren und Sie mit der Konfiguration des Servers spielen zu lassen, ohne den mühsamen Prozess der Weiterleitung von Datenverkehr an einen anderen Server durchlaufen zu müssen.


1
2017-07-30 21:37





Soweit wir "den eingehenden HTTP-Verkehr auf dem Live-Server auf einen oder mehrere entfernte Server in Echtzeit duplizieren möchten" gibt es eine Möglichkeit, die oben nicht erwähnt wurde, nämlich einen Mirror-Port auf dem Switch zu konfigurieren, mit dem er verbunden ist.

Bei Cisco Catalyst Switches heißt das SPAN (mehr Info Hier). In einer Cisco-Umgebung können Sie sogar den gespiegelten Port auf einem anderen Switch haben.

Aber der Zweck davon ist für die Verkehrsanalyse, so wird es unidirektional - Stichwort im zitierten Text im ersten Absatz oben: eingehende. Ich glaube nicht, dass der Port Rückverkehr erlaubt, und wenn ja, wie würden Sie mit doppeltem Rückverkehr umgehen? Das wird wahrscheinlich nur Ihr Netzwerk zerstören.

Also ... wollte nur eine Möglichkeit zu Ihrer Liste hinzufügen, aber mit der Einschränkung, dass es in der Tat für den Einbahnverkehr sein wird. Vielleicht können Sie einen Hub auf diesen Mirror-Port setzen und doppelte Serverantworten von einem lokalen Client-Simulator erhalten, der initiierte Sitzungen aufnimmt und darauf reagiert, aber dann würden Sie eingehenden Datenverkehr auf Ihren doppelten Server duplizieren ... wahrscheinlich nicht das, was Sie tun wollen.


0
2018-01-29 16:45



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, wenn es um Hardware-Änderungen geht. Ich habe bereits gebeten, 2 Server auf einer zweiten nic direkt zu verbinden. Diese Aktion kombiniert mit einem lokalen Netzwerk für nur diese 2 Server würde es mir ermöglichen, IPTABLES mit TEE zu verwenden. Aber für diese Alternative müssten wir die externen IPs der Server ändern, was ein NoGo ist, da Client-Geräte für die Verbindung mit der eingestellten IP konfiguriert sind. - Sise


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

https://github.com/losnir/ampel

Es ist sehr eigensinnig und unterstützt derzeit:

  • GET Verwenden der Round-Robin-Auswahl (1: 1)
  • POST Verwenden der Anforderungsaufteilung Es gibt kein Konzept von "Master" und "Schatten" - das erste Backend, das antwortet, ist dasjenige, das der Client-Anfrage dient, und dann werden alle anderen Antworten verworfen.

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


0
2017-07-23 10:06



Node.js ist eine sehr seltsame Sprache für eine Anwendung wie diese, die eine sehr hohe Leistung erfordert. Ich bin mir nicht sicher, ob dies jemals produktionsfertig sein wird. - Michael Hampton♦
Du liegst absolut richtig. Das sollte nicht sehr performant sein - einfach einfach zu schreiben (für mich). Ich denke, es hängt von der erforderlichen Belastung ab. Ich konnte allerdings etwas über 1.000 RPS auf einem Low-End-Rechner (2 Kerne) erreichen. - losnir


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


-1
2017-10-16 09:12



Hallo und willkommen bei Serverfault. Bitte können Sie eine detailliertere Antwort geben? Was macht das Programm genau? Ist es in C geschrieben? - bgtvfr