一、子查询
子查询只是模拟 HTTP 接口的形式, 没有 额外的 HTTP/TCP 流量,也 没有 IPC (进程间通信) 调用。所有工作在内部高效地在 C 语言级别完成。
子查询只能在一个 location
里调用其它 一个或多个 `location。
二、capture
res = ngx.location.capture(uri, options?)
发起子查询
返回一个包含四个元素的 Lua 表 (res.status
,res.header
,res.body
, 和res.truncated
)。
作用域:rewrite_by_lua *
,access_by_lua *
,content_by_lua *
示例:
res = ngx.location.capture(
'/foo/bar',
{ method = ngx.HTTP_POST, body = 'hello, world' }
)
三、capture_multi
res1, res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ... })
发起多个并发子查询
作用域:rewrite_by_lua *
,access_by_lua *
,content_by_lua *
示例:
res1, res2, res3 = ngx.location.capture_multi{
{ "/foo", { args = "a=3&b=4" } },
{ "/bar" },
{ "/baz", { method = ngx.HTTP_POST, body = "hello" } },
}
if res1.status == ngx.HTTP_OK then
...
end
if res2.body == "BLAH" then
...
end
四、举例
比如京东商品页页面,会分为商品价格,除了商品本身信息外,下方还会有推荐,最佳组合(sd卡,一些套餐),左边栏还会告诉你看了这个手机的人还会看其他哪些手机,中间手机性能详细介绍,下面还有用户评价,页面实际挺复杂的。
1、一般做法
每个功能做一个api,比如价格,加到购物车,最佳组合,看了看,会有8或9个api。你的前端,一次调用这个8,9个api会有问题:
1.卡顿:http请求数量会比较多,在流量比较大的时候,比如6.18或者11.11。页面给用户的感觉会卡顿,因为它会发起多个http请求
2.无法降级服务:比如其中某一个不关键的服务宕机了,前端页面可能会一直卡在那里,浏览器界面一直在转。一个不关键的信息,影响用户购买。主要服务不能受不主要服务影响。这个业务如果放在前端控制,判断哪一个api是否重要,导致前端业务太重。
2、正确的做法
最好给前端只有一个api接口,这一个api接口给前端需要的所有东西。那一些信息是否重要都在这一个api接口返回给前端,前端业务变轻,后端几个api做业务重构,做调整会很容易,前端无感知变化。
可以使用openresty的capture子查询特性完成,每一个location只做一个功能,用openresty自带自查询功能串起来每个location,如果某一个location出问题,可以把这个location砍掉,或者设置超时时间特别短。这样即使你有问题,给前端返回的时间还是这些时间。
商品详情页优化:
openresty的capture_mulit,可以并行发起多个子查询,按照顺序返回,返回时间是最长location的请求时间,只要最慢的location,这个cature_mulit完成
五、子查询作用
减少网络请求。
方便配置降级服务。
子查询文档参考: https://github.com/openresty/lua-nginx-module#ngxlocationcapture