0%

# openresty

Posted on 2019-06-18 Edited on 2020-01-12 In nginx Views: Views: Disqus:

目前公司要对一些新的产品功能做灰度测试，因为在后端业务代码层面添加判断比较麻烦，所以想在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
    8
    http {
      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'

使用总结

后续：

1. 一开始在本地环境的时候使用content_by_lua_file只关注了头，后来发到测试环境发现请求内容都没代理转发到后端服务上
   网上查了下发现content_by_lua_file是将请求的所有内容包括response都用这里面的lua脚本生成了，content这个词就表示是请求内容
   后来改成了access_by_lua_file就正常了，只是要去获取请求内容和修改响应头，并不是要完整的接管请求

2. 后来又碰到了一个坑是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这个参数配置调大一点就好了

3. 还有就是lua的异常捕获，网上看一般是用pcall和xpcall来进行保护调用，因为问题主要出在cjson的decode，这里有两个解决方案，一个就是将cjson.decode使用pcall封装，

       1
       2
       3
       4
       5
       6
       7
       8
       9
       10
       local 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
       7
       local json = require("cjson.safe")
       local str = [[ {"key:"value"} ]]

       local t = json.decode(str)
       if t then
           ngx.say(" --> ", type(t))
       end

   cjson.safe包会在解析失败的时候返回nil

4. 还有一个是redis链接时如果host使用的是域名的话会提示“failed to connect: no resolver defined to resolve “redis.xxxxxx.com””，这里需要使用nginx的resolver指令，
   `resolver 8.8.8.8 valid=3600s;`

5. 还有一点补充下
   就是业务在使用redis的时候使用了db的特性，所以在lua访问redis的时候也需要执行db，这里lua的redis库也支持了这个特性，可以使用instance:select(config:get(‘db’))来切换db

6. 性能优化tips
   建议是尽量少使用阶段钩子，例如content_by_lua_file，*_by_lua

7. 发现一个不错的openresty站点
   地址

请我喝杯咖啡

WeChat Pay

Alipay

- Post author: Nicksxs
- Post link: https://nicksxs.me/2019/06/18/openresty/
- Copyright Notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.