HttpLuaModule create asynchronous subrequests

Guido Accardo guido at motrixi.com
Wed Nov 12 20:20:35 UTC 2014


Hi,

   With the help of HttpLuaModule I'm trying to duplicate every request
into two upstreams. Here is my configuration:

site.conf
---

upstream prod_upstream {
        server 127.0.0.1:5000;
        server 127.0.0.1:5001;
}

upstream dev_upstream {
        server 127.0.0.1:6000;
}

server {
        location /prod {
                proxy_pass http://prod_upstream/;
        }

        location /dev {
                proxy_pass http://dev_upstream/;
        }

        location / {
                error_log "/tmp/error.log";
                content_by_lua_file /etc/nginx/luas/duplicator.lua;
        }
}

duplicator.lua
---

ngx.req.read_body()
local arguments = ngx.var.args

r1, r2 = ngx.location.capture_multi {
        { '/prod/', { args = arguments, share_all_vars = true } },
        { '/dev/', { args = arguments, share_all_vars = true } },
}

ngx.print(r1.body)


So far so good, all traffic destined to prod is being duplicated to dev and
ONLY prod response is forwarded the client.

>From the documentation here
http://wiki.nginx.org/HttpLuaModule#ngx.location.capture_multi :

" ... This function will not return until all the subrequests terminate ...
"

That is where my problem starts:

I'm working with a real time distributed system so the response time can't
be longer than 50ms. Dev is definitely slower so I can't wait for dev
response. Also Imagine if /dev is broken the timeout will take too much
time.

I'm thinking about making /dev calls in an asynchronous way if possible.

My second approach:

duplicator_v2.lua:
---

gx.req.read_body()
local arguments = ngx.var.args

r1 = ngx.location.capture('/prod/', { args = arguments, share_all_vars =
true })
ngx.print(r1.body)

r2 = ngx.location.capture('/dev/', { args = arguments, share_all_vars =
true })


>From the documentation of ngx.print:

" ... This is an asynchronous call and will return immediately without
waiting for all the data to be written into the system send buffer ..."

I was hopping that splitting the captures and using ngx.print before the
second call will do what I need, answer to the client and continue with
calling /dev but that doesn't happen, works exactly as the first approach.

My final tests was this ugly configuration:

duplicator_v2.lua:
---

gx.req.read_body()
local arguments = ngx.var.args

r1 = ngx.location.capture('/prod/', { args = arguments, share_all_vars =
true })
ngx.print(r1.body)
ngx.eof()

r2 = ngx.location.capture('/dev/', { args = arguments, share_all_vars =
true })


Here, prod response is sent immediately as I want and dev receives the
traffic but the connection is closed the I got a Broken Pipe (which makes
sense).


Is there a way to do capture calls in a asynchronous mode or to achieve
this in other way?

Thank you in advance,


-- 
---
Guido Accardo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20141112/b5d159e7/attachment.html>


More information about the nginx mailing list