On Tue, 19 Jul 2016 15:28:25 +0530
Sachin Shetty <sshe...@egnyte.com> wrote:

> 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?


Hi,

The processing of the request by haproxy is pending while the execution
of the lua action.

The execution of "tcp-request content" directives are done before the
execution of "http-request". So HAProxy executes first the capture and
them the action which populate the map.

Normally, HAProxy display a warning when it start, if it detects a
configuration order different than a execution order. Try to replace the
"tcp-request" by "http-request".


> 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?


It seems that you use a good 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. 


Yes, the usage of core.tcp() require some yields, and haproxu doesn't
support yield during the execution of sample-fetches. For bypassing
this problem, I use variables. I store the expected result in a
variable during the execution of the action, and I use these variable
with the use_backend directive.


Thierry


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

Reply via email to