openresty
目前公司要对一些新的产品功能做灰度测试,因为在后端业务代码层面添加判断比较麻烦,所以想在nginx上做点手脚,就想到了openresty
前后也踩了不少坑,这边先写一点
首先是日志error_log logs/error.log debug;
需要nginx开启日志的debug才能看到日志
使用 lua_code_cache off
即可, 另外注意只有使用 content_by_lua_file
才会生效1
2
3
4
5
6
7
8http {
lua_code_cache off;
}
location ~* /(\d+-.*)/api/orgunits/load_all(.*) {
default_type 'application/json;charset=utf-8';
content_by_lua_file /data/projects/xxx/current/lua/controller/load_data.lua;
}
使用lua给nginx请求response头添加内容可以用这个1
ngx.header['response'] = 'header'
后续:
一开始在本地环境的时候使用content_by_lua_file只关注了头,后来发到测试环境发现请求内容都没代理转发到后端服务上
网上查了下发现content_by_lua_file是将请求的所有内容包括response都用这里面的lua脚本生成了,content这个词就表示是请求内容
后来改成了access_by_lua_file就正常了,只是要去获取请求内容和修改响应头,并不是要完整的接管请求后来又碰到了一个坑是nginx有个client_body_buffer_size的配置参数,nginx在32位和64位系统里有8K和16K两个默认值,当请求内容大于这两个值的时候,会把请求内容放到临时文件里,这个时候openresty里的ngx.req.get_post_args()就会报“failed to get post args: requesty body in temp file not supported”这个错误,将client_body_buffer_size这个参数配置调大一点就好了
还有就是lua的异常捕获,网上看一般是用pcall和xpcall来进行保护调用,因为问题主要出在cjson的decode,这里有两个解决方案,一个就是将cjson.decode使用pcall封装,
1
2
3
4
5
6
7
8
9
10local decode = require("cjson").decode
function json_decode( str )
local ok, t = pcall(decode, str)
if not ok then
return nil
end
return t
end这个是使用了pcall,称为保护调用,会在内部错误后返回两个参数,第一个是false,第二个是错误信息
还有一种是使用cjson.safe包1
2
3
4
5
6
7local json = require("cjson.safe")
local str = [[ {"key:"value"} ]]
local t = json.decode(str)
if t then
ngx.say(" --> ", type(t))
endcjson.safe包会在解析失败的时候返回nil
还有一个是redis链接时如果host使用的是域名的话会提示“failed to connect: no resolver defined to resolve “redis.xxxxxx.com””,这里需要使用nginx的resolver指令,
resolver 8.8.8.8 valid=3600s;
还有一点补充下
就是业务在使用redis的时候使用了db的特性,所以在lua访问redis的时候也需要执行db,这里lua的redis库也支持了这个特性,可以使用instance:select(config:get(‘db’))来切换db发现一个不错的openresty站点
地址