5
votes

We have Similar setup to this diagram

enter image description here

Where request arrives to HAProxy, it get's roundrobin balanced to any servers, backend server checks its cache and if resource is not on that server it issues redirect with header set to the correct server IP.

Second time request arrives to HAProxy, it detects that the header with backend server is there, but how can I take that IP and direct request directly to it?

For example, second time request arrives to haproxy it has header X-BACKEND-IP=10.0.0.5

So instead haproxy trying to load balance that request, I want it to read the header, take that IP and go directly to that backend.

Is that possible? If not, would it be possible with nginx ?

1
So your original behavior is: 1) the HAProxy receives the original HTTP request -> 2) detects that the requested resource is not available -> 3) Forwards the original request with an additional HTTP header field X-BACKEND-IPwith an available server to itself -> 4) detects that the requested resource is available -> 5) sends request to resource. Your goal is to eliminate step 3 and 4? - Liam Kelly
@LiamKelly Not really, the HAProxy does not set the header nor does the redirection. That is all done by the backend service itself. 1) HAPRoxy receives request -> 2) "blindly" round-robin it to any backend next in line -> 3) the backend service itself decides if it can serve that request or what other backend it should go to. If it decides it should go somewhere else, it sets the X-BACKEND-IP header and redirects back to haproxy (all fine up to this point) -> 4) HAProxy will take that header and route directly to the IP from the header - Tomas
If I am understanding this correctly, it seems most efficient for the backend service to send the request to the final server directly. The first backend service knows where the request should go, so why burden HAProxy? If the two backend servers are not directly routable, you can put an ip-forwarding rule (OSI Layer 3, not a request proxy rule) to still use the HAProxy machine as a central routing point. - Liam Kelly
Looking for sticky sessions? blog.haproxy.com/2012/03/29/… - Dmitry MiksIr
@DmitryMiksIr Unfortunately sticky sessions in this case won't work - Tomas

1 Answers

3
votes

Assuming you're happy with trusting the IP in the header of the second request, then yes, you can do it with use-server:

backend bk_foo
  [...]
  server srv_0a_00_01_05 10.0.1.5:80 weight 100
  server srv_0a_00_02_05 10.0.2.5:80 weight 100
  use-server %[req.hdr(x-backend-ip),lower,map_str(/etc/haproxy/hdr2srv.map,srv_any)] if { req.hdr(x-backend-ip),lower,map_str(/etc/haproxy/hdr2srv.map) -m found }

Contents of /etc/haproxy/hdr2srv.map:

#ip srv_name
# hex of IP used for names in this example
10.0.1.5  srv_0a_00_01_05
10.0.2.5  srv_0a_00_02_05

If you need to down one of the servers, you should dynamically update the map to remove it, so that the requests with the header set get redirected again.

If you have multiple backends, you can do similar with use_backend.