HAProxy - Sie müssen der ACL einen URL-Parameter hinzufügen, um zwischen Diensten mit derselben URL, aber auf unterschiedlichen Ports zu unterscheiden

HAProxy - Sie müssen der ACL einen URL-Parameter hinzufügen, um zwischen Diensten mit derselben URL, aber auf unterschiedlichen Ports zu unterscheiden

Ich habe mehrere Dienste, die auf unterschiedlichen Ports laufen und alle die gleichen URI-Pfade verwenden. Beispiel:

New York Housing Service
127.0.0.1:8080/homes
127.0.0.1:8080/prices

Las Vegas Housing Service
127.0.0.1:8081/homes
127.0.0.1:8081/prices

Das hat bisher gut geklappt, aber jetzt muss ich haproxy einrichten, um die Last der Dienste auszugleichen. Daher muss ich sie natürlich für den Inhaltswechsel unterscheiden können. Ich stelle mir vor, dass ich dem Pfad in der ACL einen Parameter hinzufügen würde, um zwischen den beiden Backends zu unterscheiden. In diesem Fall würde ich einen URL-Parameter in der ACL einfügen, gefolgt von den tatsächlichen Pfadparametern für die Anwendung:


frontend http
  maxconn 2000
  bind 0.0.0.0:5000  

  acl new-york path_reg -i /newyork.*
  use_backend nyc-server if new-york

  acl las-vegas path_reg -i /lasvegas.*
  use_backend lv-server if las-vegas

backend nyc-server
  server www.test.com 127.0.0.1:8080 maxconn 100

backend lv-server
  server www.test.com 127.0.0.1:8081 maxconn 100

In diesem Setup gelange ich zu 127.0.0.1:5000/newyork/home und lande dann bei 127.0.0.1:8080/home, während 127.0.0.1:5000/lasvegas/home mich zu 127.0.0.1 bringt:8081/home. Meine bisherigen Versuche haben einfach einen 404-Fehler zurückgegeben. Ich habe die Dokumentation durchgesehen, aber nichts gefunden, das meinem Anwendungsfall entspricht. Daher wäre ich für jede Hilfe sehr dankbar.

EDIT: Ich habe vergessen zu erwähnen, dass ich haproxy 1.5.18 verwende

Antwort1

Die Backend-Dienste antworten mit HTTP 404-Fehlern, da Ihre HAPROXY-Konfiguration den URL-Pfad derzeit unverändert weiterleitet. Beispielsweise wird eine HTTP-Anforderung für an das Backend als http://127.0.0.1:5000/newyork/home/wtc.pngweitergeleitet .nyc-serverhttp://127.0.0.1:8000/newyork/home/wtc.png

$ wget -4O /dev/null http://localhost:5000/newyork/homes/wtc.png
--2020-02-01 13:00:09--  http://localhost:5000/newyork/homes/wtc.png
Resolving localhost (localhost)... 127.0.0.1, 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:5000... connected.
HTTP request sent, awaiting response... 404 File not found
2020-02-01 13:00:09 ERROR 404: File not found.
$ python -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
127.0.0.1 - - [01/Feb/2020 13:00:09] code 404, message File not found
127.0.0.1 - - [01/Feb/2020 13:00:09] "GET /newyork/homes/wtc.png HTTP/1.1" 404 -

HAproxy sollte so konfiguriert werden, dass es URL-Pfade übersetzt, indem es beim Abrufen von Ressourcen aus Backends die erste Pfadkomponente entfernt. Ich würde vorschlagen, dass Sie der reqrep Definition des Frontends eine Direktive hinzufügen, die die erste Zeile des HTTP-Anforderungsheaders manipuliert und etwas wie GET /newyork/homes/wtc.png HTTP/1.1Folgendes übersetzt GET /homes/wtc.png HTTP/1.1.

frontend http
  reqrep ^([A-Z]+)\ /+[^/]+(/+.*)?$  \1\ \2

Dies funktioniert jedoch nicht, da HAproxy reqrepDirektiven vor use-backendEinsen auswertet und dadurch die Backend-Auswertung unterbricht:

$ wget -4O /dev/null http://localhost:5000/newyork/homes/wtc.png
--2020-02-01 13:54:55--  http://localhost:5000/newyork/homes/wtc.png
Resolving localhost (localhost)... 127.0.0.1, 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:5000... connected.
HTTP request sent, awaiting response... 503 Service Unavailable
2020-02-01 13:54:55 ERROR 503: Service Unavailable.

Ein zweiter funktionierender Ansatz ist das Umschreiben des URL-Pfads in Backend-Definitionen. Abhängig von der Anzahl der Backends im Dienst reqrepist das Schreiben von Anweisungen und das Konfigurieren jedes Backends zum Durchführen des URL-Umschreibens jedoch fehleranfällig.

backend nyc-server
  server www.test.com 127.0.0.1:8080 maxconn 100
  reqrep ^([A-Z]+)\ /+[^/]+(/+.*)?$  \1\ \2

backend lv-server
  server www.test.com 127.0.0.1:8081 maxconn 100
  reqrep ^([A-Z]+)\ /+[^/]+(/+.*)?$  \1\ \2
$ wget -4O /dev/null http://localhost:5000/newyork/homes/wtc.png
--2020-02-01 14:02:29--  http://localhost:5000/newyork/homes/wtc.png
Resolving localhost (localhost)... 127.0.0.1, 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:5000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 456892 (446K) [image/png]
Saving to: ‘/dev/null’

/dev/null        100%[===============>] 446.18K  --.-KB/s    in 0s      

2020-02-01 14:02:29 (1.83 GB/s) - ‘/dev/null’ saved [456892/456892]

$ python -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
127.0.0.1 - - [01/Feb/2020 14:02:29] "GET /homes/wtc.png HTTP/1.1" 200 -

verwandte Informationen