Hello!
2015-08-05 14:54 GMT+08:00 <mike1...@gmail.com>:
> A会请求B中内容,如果B中没有内容会转发后获取,那么问题来了。
> accesslog
> 中需要记录$upstream_addr和$upstream_response_time转发的地址以及响应时间,A中是没有这两个变量的数值的,
> 想通过capture变量的传递,传送给A,让A记录。
> 但是B中获取$upstream_addr和$upstream_response_time在body_by_filter阶段都无法获取到数值,
一般建议通过子请求中的 ngx.ctx 来向父请求传递数据。$upstream_xxx 变量只在配置了 upstream 模块(比如
ngx_proxy 模块)的 location 中才有意义,而在你给的例子中,只在 location B 中有意义。
当然,即使是在 location B 中,$upstream_xxx
变量只在足够晚的时间阶段才有有意义的值。下面我给出一个修改过了的最小化了的例子,经测试证实可以满足你的需求:
location = /A {
content_by_lua '
local ctx = {}
local res = ngx.location.capture("/B", { ctx = ctx })
if res then
ngx.say("/B response status: ", res.status)
ngx.say("/B upstream addr: ", ctx.upstream_addr)
ngx.say("/B upstream response time: ",
ctx.upstream_response_time, "s")
end
';
}
location = /B {
internal;
proxy_pass http://www.baidu.com/;
body_filter_by_lua '
local eof = ngx.arg[2]
if eof then -- ensure we are at the last data chunk sent
by the upstream.
local ctx = ngx.ctx
ctx.upstream_addr = ngx.var.upstream_addr
ctx.upstream_response_time = ngx.var.upstream_response_time
end
';
}
请求 /A 得到的一次典型结果如下:
/B response status: 200
/B upstream addr: 119.75.218.70:80
/B upstream response time: 0.052s
显然,我们在 location = /A 中得到了 /B 中的所有 $upstream_xxx 的值。
当然,为方便起见,我在这个例子(以及后面的例子)中并没有让 /A
记录访问日志,而是直接将结果输出到响应。既然我们都可以输出结果为响应,自然更可以将结果记录到访问日志了。
> 而下一个阶段是log_by_lua,看了文档其中有 This does not replace the current access logs, but
> runs after.这么一句话,显然获取的数值太晚了。
> 这种情况有什么解决办法呢?
>
貌似你对这句话的理解产生的偏差。在你这个例子中,log_by_lua 是运行在 /B 这个子请求中的,而记录访问日志的却是 /A
这个主请求。这两个都不是同一个请求,所以自然没有任何关系。下面这个例子演示了如何使用 log_by_lua
来实现你的需求,同样已经在我本地测试通过:
location = /A {
content_by_lua '
local ctx = {}
local res = ngx.location.capture("/B", { ctx = ctx })
if res then
ngx.say("/B response status: ", res.status)
ngx.say("/B upstream addr: ", ctx.upstream_addr)
ngx.say("/B upstream response time: ",
ctx.upstream_response_time, "s")
end
';
}
location = /B {
internal;
proxy_pass http://www.baidu.com/;
log_subrequest on; # ensure we have log_by_lua running in subrequests
access_log off; # ensure we do not get access log entries for
subrequests.
log_by_lua '
local ctx = ngx.ctx
ctx.upstream_addr = ngx.var.upstream_addr
ctx.upstream_response_time = ngx.var.upstream_response_time
';
}
访问 /A 得到的一次典型输出为
/B response status: 200
/B upstream addr: 119.75.217.109:80
/B upstream response time: 0.047s
显然与前面使用 body_filter_by_lua 的例子是类似的。
值得一提的是,这个使用 log_by_lua 的例子在性能上要略高于前面使用 body_filter_by_lua 的例子,因为
body_filter_by_lua 可能对较大的响应体被调用多次,而且 ngx.arg[1] 这个东西会产生 meta method
调用,也有一点点额外的开销。虽然我觉得这种区别在真实的生产环境中倒也不至于可以测量出来,但还是值得提醒一下。
Regards,
-agentzh