I'm working on a project to switch between backends based on whether a URL
path prefix is found in a map file. Straightforward enough.

In the runtime environment, the haproxy config is generated from a template
and it is possible that a configured backend is not available despite being
listed in the map file.

What I'd like to do to write my config to try the preferred backend, fall
back to a special backend if the preferred one is not available, and only
then go to the default backend as a last resort.

I found two prior mailing list threads on this topic:
"try other backend when backlog is full or backend unavailable, but only in
that case"
https://www.mail-archive.com/[email protected]/msg07493.html

"HAProxy - Try Multiple Backends Sequentially?"
https://www.mail-archive.com/[email protected]/msg26057.html


Example config for what I'd like to do:

# Get the backend for the request path prefix
http-request set-var(req.pref_backend)
path,map_beg(path-prefix-backends.map)

# If the variable was set, use it to choose the backend
use_backend be_%[var(req.pref_backend)] if { var(req.pref_backend) -m found
}

# If the path prefix is in the map, but the backend isn't up, handle
specially
use_backend be_configured_path_broken if { var(req.pref_backend) -m found }

# Last resort use the no_match backend for a generic error response
default_backend no_match


The problem is that if the first "use_backend" command resolves to a
backend that does not exist, the "default_backend" is used. This is exactly
as documented, so it's not a surprise, but I was vaguely hoping for
something different :)

"If <backend> is a log-format string instead, no check may be done at
configuration time, so the backend name is resolved dynamically at run
time. If the resulting backend name does not correspond to any valid
backend, no other rule is evaluated, and the default_backend directive is
applied instead."


My first attempt to work around this limitation was to use "nbsrv" but it
appears to accept only literal strings and not log-format strings?

# Does not work for me:
acl is_pref_backend_available nbsrv(%[var(req.pref_backend)]) gt 0


Proposal:

New acl "backend_exists(string or log-format-string)" - returns a bool if a
backend is defined at runtime.

Augment acl "nbsrv(string)" to "nbsrv(string or log-format-string)" -
returns an int count of healthy backends at runtime.


Lua Escape Hatch

It would appear that I could do this in Lua, following the example in this
HAProxy Tech blog post:
https://www.haproxy.com/blog/5-ways-to-extend-haproxy-with-lua/

The Lua option feels a little unfortunate because it would have to iterate
of core.backends and do a string comparison for each backend to find the
one that matches the map lookup, or finish iterating without finding a
match - and so then set a variable to use the special fallback.

So I do think it would be helpful to have an acl for this, since it is
possible today to write a "use_backend" command that references a
non-existent backend at runtime and I'd like to catch those cases.

Thanks,
Aaron

Reply via email to