Hi,
We always had a unique requirement of picking a backend based on response
from a external http service. In the past we have got this working by
routing requests via a modified apache and caching the headers in maps for
further request, but now I am trying to simplify our topology and trying to
get this done using just haproxy and lua.
I am running in to some problems:
Lua method:
function choose_backend(txn)
local host = txn.http:req_get_headers()["host"][0]
core.Alert("Getting Info:" .. host)
local sock = core.tcp()
sock:connect("127.0.0.1", 6280)
sock:send("GET /eos/rest/private/gds/l1/1.0/domain/" .. host ..
"\r\n")
result = sock:receive("*a")
sock:close()
core.Alert("Received Response:" .. result .. "<")
core.set_map("/tmp/proxy_webui.map", host, result)
core.Alert("Map Set:" .. host .. "-->" .. result .. "<")
end
core.register_action("choose_backend", { "http-req" }, choose_backend)
Haprpxy Conf:
frontend luatest
mode http
maxconn 10000
bind *:9000
use_backend %[hdr(host),lower,map(/tmp/proxy_webui.map)] if FALSE #
To declare the map
http-request lua.choose_backend
tcp-request content capture hdr(host),map(/tmp/proxy_webui.map) len
80
acl is_ez_pod capture.req.hdr(0) http://127.0.0.1:6280
use_backend ez_pod if is_ez_pod
backend ez_pod
server ez_pod 192.168.56.101:6280 maxconn 2
There are some issues:
1. I do see Map Set called correctly in the logs, but the haproxy capture
does not find the key in the map for the first request. Is this related to
async execution of luna routine?
2. I expected subsequent requests to see the value atleast, but even that is
not consistent, some request see the value in the map and some don¹t
Is there a better way to do this? I already found that I cannot invoke the
luna routine with use_backend because yield is not allowed in a sample fetch
context.
What would be the best way to achieve this, our requirement is similar to
what can be done with redis+nginx here:
http://openresty.org/en/dynamic-routing-based-on-redis.html except for we
have an http service that decides the backend instead of a redis service.
Thanks
Sachin