Ist die Verwendung eines dynamischen Ports eine gute Lösung für Software-Testserver?

608
Christian Hujer

Zum Testen (automatisiert, TDD, ATDD / BDD, das auch auf einer CI / CD-Pipeline ausgeführt wird) möchte ich einen Server an einem dynamischen Port ausführen. Der Test soll den Server starten, Tests durchführen und den Server stoppen. Dies soll in einer CI / CD-Umgebung sowie auf Entwicklungsmaschinen möglich sein. Es muss die parallele Ausführung mehrerer Tests unterstützen. Beispielsweise kann der Entwickler in zwei Zweigen parallel arbeiten und somit parallel Tests ausführen. Die Lösung sollte auf einer Vielzahl von Betriebssystemen funktionieren, zumindest auf BSD, Darwin, Linux und Windows.

Ich sehe die folgenden Optionen, von denen keine wirklich das Problem vollständig löst. Jede hat ihre eigenen Mängel.

  • Feste Portnummer. Dies verstößt gegen das Erfordernis, parallel testen zu können. Es kann mit Containerisierung verhindert werden, aber das ist fast so, als würde man eine Kakerlake machen, nur VMs oder separate HW wären noch schlimmer. Wir haben "Process" und "Port" aus einem bestimmten Grund und sollten bei einem solchen Problem keine Containerisierung durchführen müssen. Ich würde mich für die Containerisierung entscheiden, sobald Integrationstests mehrere Server miteinander verbinden und ihre Infrastruktur in einer CI / CD-Umgebung simulieren müssen. Für Komponententests, dh das Testen eines einzelnen Servers / Dienstes isoliert, möchte ich die Containerisierung vermeiden.
  • Zufälliger Port aus dem registrierten Portbereich. Dies hat zwei Probleme. Zum einen gibt es keine Garantie dafür, dass der zufällige Port verfügbar ist. Es besteht eine geringe Chance, dass der zufällige Port aus dem registrierten Portbereich nicht verfügbar ist (bereits an einen anderen Prozess gebunden). Der registrierte Portbereich ist auch betriebssystemspezifisch. Während RFC 6056 den Zufallsportbereich eindeutig als 1024 bis 49151 beschreibt, verwenden einige Betriebssysteme wie Linux einen anderen Bereich.
  • Zufälliger Port vorab geprüft Entspricht dem Zufallsport, der Port wird jedoch auf Verfügbarkeit geprüft. Ich sehe dort die Gefahr eines Rennens. Die CI-Software prüft die Verfügbarkeit, sieht sie als frei an und startet die App mit dem Port. Zwischen der CI-Prüfung auf Verfügbarkeit und dem Aufruf der App an einen bind()anderen Prozess wurde der Port bereits gebunden.
  • Verwenden eines Ports aus dem dynamischen Portbereich, der normalerweise für kurzlebige Ports verwendet wird. Dies wird erreicht, indem das getan portvon der socketder bind()Anruf als 0. Das Betriebssystem weist den Port aus seinem dynamischen Portbereich (auch als kurzlebiger Portbereich bezeichnet) zu. Dies sah für mich nach der besten Lösung aus, bis ich von TCP-Selbstverbindung erfuhr. Jetzt wundere ich mich.

Um die TCP-Selbstverbindung zu reproduzieren, können Sie einfach ausführen while true ; do telnet localhost 50000 ; doneund einige Zeit warten. Nach einiger Zeit werden Sie feststellen, dass es Telnet gelungen ist, eine Verbindung herzustellen - zu sich selbst!

Ich denke, dass TCP Self-Connect in diesem Fall kein Problem sein sollte. Es gibt eine, bind()aber keinen connect()Anruf vom Server, sondern einlisten()anrufen, so dass der Port gesperrt ist und nicht verwendet wird, bis er frei wird. Dann wird diese Portnummer für den Testclient verwendet, um eine Verbindung herzustellen. Die TCP-Selbstverbindung wäre nur dann ein Problem, wenn der Test fortgesetzt wird, obwohl der Server keine Verbindung herstellen kann, und wiederholt versucht, eine Verbindung mit dem Server herzustellen (erfolglos) und die Tests fehlschlagen, bis einer der Tests in die Falle der TCP-Selbstfalle gerät. verbinden und müsste der Test-Client also mit sich selbst sprechen. Das würde zu einer Zeitüberschreitung führen, was bedeutet, dass der Test langsam war, aber dieser Test wäre von Anfang an sowieso verpfuscht (er sollte keine Tests durchführen, wenn der Server nicht erfolgreich gestartet werden konnte) Ich halte dies nicht für ein vernünftiges Szenario.

Die Frage ist also: Ist die Verwendung eines dynamischen Ports ( bind()von Port 0) eine gute Lösung, um Portkonflikte bei Softwaretestservern zu vermeiden?

0

0 Antworten auf die Frage