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
Lua | NGINX :
" … 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,