HAProxy: es necesario agregar un parámetro de URL a ACL para diferenciar entre servicios con la misma URL, pero en diferentes puertos.

HAProxy: es necesario agregar un parámetro de URL a ACL para diferenciar entre servicios con la misma URL, pero en diferentes puertos.

Tengo varios servicios que se ejecutan en diferentes puertos, cada uno de los cuales utiliza las mismas rutas URI. Por ejemplo:

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

Esto ha estado bien hasta ahora, pero ahora necesito configurar haproxy para equilibrar la carga de los servicios. Como tal, obviamente necesito poder diferenciarlos para cambiar de contenido. Lo que imagino que haría es agregar un parámetro a la ruta en la ACL para diferenciar entre los dos backends, en este caso teniendo un parámetro de URL en la ACL, que sería seguido por los parámetros de ruta reales para la aplicación:


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

En esta configuración, ir a 127.0.0.1:5000/newyork/home me llevará a 127.0.0.1:8080/home, mientras que 127.0.0.1:5000/lasvegas/home me lleva a 127.0.0.1:8081/hogar. Mis intentos hasta ahora simplemente han devuelto un error 404. He estado revisando la documentación, pero no vi nada que coincidiera con mi caso de uso, por lo que cualquier ayuda sería muy apreciada.

EDITAR: Olvidé mencionar que estoy usando haproxy 1.5.18

Respuesta1

Los servicios backend responden con errores HTTP 404 porque su configuración HAPROXY actualmente está reenviando la ruta de la URL tal como está. Por ejemplo, una solicitud HTTP http://127.0.0.1:5000/newyork/home/wtc.pngse reenvía al nyc-serverservidor como http://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 debe configurarse para traducir las rutas de las URL eliminando el primer componente de la ruta mientras se obtienen recursos de los servidores. Le sugeriría que agregue una reqrep directiva en la definición de la interfaz, que está destinada a manipular la primera línea del encabezado de la solicitud HTTP y traducir algo como GET /newyork/homes/wtc.png HTTP/1.1a GET /homes/wtc.png HTTP/1.1.

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

Sin embargo, no funcionará porque HAproxy evalúa reqreplas directivas antes que use-backendlas demás, rompiendo así la evaluación de backend:

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

Un segundo enfoque de trabajo es reescribir la ruta URL en las definiciones de backend. Sin embargo, dependiendo de la cantidad de backends en servicio, escribir reqrepdirectivas y configurar cada backend para realizar la reescritura de URL es propenso a errores.

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 -

información relacionada