OpenResty
最近用 OpenResty 比较多,除了一些业务逻辑的实现也做了 AB 组灰度相关的实现。OpenResty 是在 Nginx 基础上做的扩展,应该算是国人开源项目中很成功的一个。在做的过程中写了不少 Lua 代码,写 Lua 代码的体验就是库好少,语言好简单。
OpenResty lua 编程相关参考
其中 Readme 要看完,大概会有一个全局的了解。最佳实践辅助看看。
理解 Nginx 处理的几个阶段:http://www.nginxguts.com/2011/01/phases/
处理 Response Body
在我们的实现中有一步需要给后端返回的结果里面加一段水印 (也就是一段 JS 代码),这步可以在 body_filter 这个里面做。不过需要注意 body_filter 是按流式方式处理的,需要把各个 buffer 存下来然后拼接起来。
而且后端返回的结果可能是 zip 压缩过的,所以需要解压,然后才能做替换或者拼接的操作。
local chunk, eof = ngx.arg[1], ngx.arg[2]
local buffered = ngx.ctx.buffered
if not buffered then
buffered = {} -- XXX we can use table.new here
ngx.ctx.buffered = buffered
end
if chunk ~= "" then
buffered[#buffered + 1] = chunk
ngx.arg[1] = nil
end
if eof then
local whole = table.concat(buffered)
ngx.ctx.buffered = nil
-- try to unzip
local status, debody = pcall(com.decode, whole)
if status then whole = debody end
-- try to add or replace response body
local js_code = ....
whole = whole .. js_code
ngx.arg[1] = whole
end
最后因为修改了 response body,所以需要修改 header filter 里面的部分:
ngx.header.content_length = nil
ngx.header.content_encoding = nil
容易出现的 bug
尽量使用 local 变量: 具体的解释,我在实践的过程中出现过变量乱窜的情况,结果发现是没有是用 local。
ngx.ctx 比 ngx.var 性能要好很多,但是在执行了 ngx.exec 后在子请求里 ctx 不一样,在我们的项目里大部分是用的是 ngx.var。使用 ngx.var 需要注意的是需要在 Nginx 配置文件里面提前声明。另外ngx.ctx 在使用的时候也有需要注意的地方
不要使用错误码来做内部跳转,使用 ngx.exec 很方便。