5.OpenResty系列之深入理解(一)
2023-12-23 22:47:53
本文基于Centos8进行实践,请读者自行安装OpenResty。
1. 内部调用
进入默认安装路径
cd /usr/local/openresty/nginx/conf
vim nginx.conf
location /sum {
# 只允许内部调用
internal;
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.print(tonumber(args.a) + tonumber(args.b))
}
}
2. 并行请求
location /multi {
content_by_lua_block {
local start_time = ngx.now()
local res1, res2 = ngx.location.capture_multi( {
{"/sum", {args={a=3, b=8}}},
{"/sum", {args={a=3, b=8}}}
})
ngx.say("status:", res1.status, " response:", res1.body)
ngx.say("status:", res2.status, " response:", res2.body)
ngx.say("time used:", ngx.now() - start_time)
}
}
3. 流水线方式跳转
location /exec {
content_by_lua_block {
ngx.exec("/sum?a=6&b=8")
}
}
ngx.redirect为重定向,比如访问baidu.com会重定向https://baidu.com,
ngx.exec方法与ngx.redirect是完全不同的,前者纯粹内部跳转并且没有引入任何额外 HTTP信号
4. 获取GET与POST参数
location /print_param {
content_by_lua_block {
local arg = ngx.req.get_uri_args()
for k,v in pairs(arg) do
ngx.say("[GET ] key:", k, " v:", v)
end
ngx.req.read_body()
local arg = ngx.req.get_post_args()
for k,v in pairs(arg) do
ngx.say("[POST] key:", k, " v:", v)
end
}
}
5. 在内部方法中传参
location /test {
content_by_lua_block {
local res = ngx.location.capture(
'/print_param',
{
method = ngx.HTTP_POST,
args = ngx.encode_args({a = 1, b = '2&'}),
body = ngx.encode_args({c = 3, d = '4&'})
}
)
ngx.say(res.body)
}
}
6. 获取请求body
# 默认读取 body
lua_need_request_body on;
location /get_body_data {
content_by_lua_block {
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
7. 输出响应体
ngx.say 与 ngx.print 均为异步输出
如何优雅处理响应体过大的输出?
如果响应体比较小,这时候相对就比较随意,但是如果响应体过大,是不能直接调用 API 完成响应体输出的。响应体过大,分两种情况:
① 输出内容本身体积很大,例如大文件下载
② 输出内容本身是由各种碎片拼凑的,碎片数量庞大,例如应答数据是某地区所有地址数据
第①个情况,要利用HTTP 1.1特性CHUNKED编码来完成,利用 CHUNKED 格式,把一个大的响应体拆分成多个小的应答体,分批、有节制的响应给请求方
# 开启chunked编码
chunked_transfer_encoding on;
location /download_large_file {
content_by_lua_block {
-- ngx.var.limit_rate = 1024*1024
local file, err = io.open(ngx.config.prefix() .. "data.db","r")
if not file then
ngx.log(ngx.ERR, "open file error:", err)
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
end
local data
while true do
data = file:read(1024*1024)
if nil == data then
break
end
ngx.print(data)
ngx.flush(true)
end
file:close()
}
}
我们在/usr/local/openresty/nginx
目录下准备data.db文件,按块读取本地文件内容(每次1MB),并以流式方式进行响应。
第②个情况,其实就是要利用 ngx.print 的特性了,它的输入参数可以是单个或多个字符串参数,也可以是 table 对象
local table = {
"hello, ",
{"world: ", true, " or ", false,
{": ", nil}}
}
ngx.print(table)
将输出:
hello, world: true or false: nil
也就是说当有非常多碎片数据时,没有必要一定连接成字符串后再进行输出。完全可以直接存放在 table 中,用数组的方式把这些碎片数据统一起来,直接调用 ngx.print(table) 即可。这种方式效率更高,并且更容易被优化
欢迎关注公众号算法小生
文章来源:https://blog.csdn.net/SJshenjian/article/details/135173932
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!