nginx+lua access_by_lua_file 间接性404问题排查

一、背景说明
准备在项目中基于nginx搭建一个简易网关,实现同一域名根据不同cookie代理不同docker功能,降低前端、移动端多业务线并行测试联调成本。简单来说就是服务端有多个测试环境docker分别部署不同业务需求代码,通过在前端、移动端种植cookie(存放服务端测试环境docker IP地址)方式让其具有可选择服务端测试环境能力,大大降低联调环境配置成本。具体cookie的解析逻辑在nginx中使用lua实现。

二、问题说明
根据相应nginx+lua资料配置后,一切顺利,可正常访问。但是在配合前端、移动端研发人员进行联调时,间接频繁出现请求404情况,同一接口请求参数相同,请求时间段不同,会间接出现404报错情况,在出现404时,nginx中报错信息如下所示:

2020/01/02 17:16:51 [error] 506478#0: *2183 open() "/export/Instances/Logs/runtime/api/timer/info" failed (2: No such file or directory), client: xx.xx.xx.xx, server: www.timer.com, request: "GET" .......

从错误信息来看出现404报错时,请求是直接在nginx中找静态文件的反向代理了。我有在lua脚本中打印了执行日志信息,在出现404错误时,lua脚本正常执行成功。由于该问题间接性出现,大大增加了问题排查的难度。

三、解决方案
先说解决方案,修改nginx 中lua脚本导入方式,详细如下所示:
错误方式(会出现404):

location / {
	 default_type 'application/json';  
	 charset utf-8;  
	 lua_code_cache on;  
	 access_by_lua_file /export/Instances/timer/runtime/lua/timer.lua;
}

正确方式:

location / {
	 default_type 'application/json';  
	 charset utf-8;  
	 lua_code_cache on;  
	 content_by_lua_file /export/Instances/timer/runtime/lua/timer.lua;
}

access_by_lua:在请求访问阶段处理,用于访问控制,适用于http、server、location、location if
content_by_lua:是内容处理器,接受请求并输出响应,适用于location、location if
注:我的解决方案是试出来的,由于access_by_lua 和 content_by_lua 资料相对较少,至于最根本的原因,我还没弄明白

四、排查与总结笔记
1、前期考虑是由于配置了 lua_code_cache on ,导致lua脚本被缓存导致的,深入学习了一下,非问题根本原因。
lua_code_cache :启用或禁用指令中Lua代码的Lua代码缓存。关闭时,ngx_lua提供的每个请求都将在一个单独的Lua VM实例中运行,引用的Lua文件将不被缓存,所有使用的Lua模块都将从头开始加载;开启时,lua脚本会被缓存,需要reload nginx才能让更新后的lua脚本生效

2、考虑是lua脚本错误导致的,在lua脚本本中打印了诸多日志,最后发现出现404错误时,lua脚本可正常执行,输出日志信息
记录常用命令:

---请求header
local reqHeaders = ngx.req.get_headers();
----请求类型
local reqType= ngx.var.request_method;
---请求cookie
local reqCookie = reqHeaders["cookie"];
local pcIp = ngx.var.cookie_pcip;
local appIp = ngx.var.cookie_appip;
--请求URL
local requestUri = ngx.var.request_uri;
--请求域名地址
local requestHost = ngx.var.host;

五、未完待续
继续查找 access_by_lua  和 content_by_lua 配置的相关资料
以上问题中lua 返回代码如下所示:

local timerHttp = require "resty.http"
---Post 请求
local function http_post(url,headerParm,body,timeout)
    local httpc = timerHttp.new();
    timeout = timeout or 30000;
    httpc:set_timeout(timeout);
    local res, err_ = httpc:request_uri(url, {
        method = "POST",
        body = body,
        keepalive=false,
        headers = headerParm;
    })
    httpc:set_keepalive(5000, 100)
    return res,err_;
end

local reqResult,reqErr = http_post(nowUrl,reqHeaders,reqBody,30000);
if(reqResult.status==200) then
	ngx.say(reqResult.body);
	return ;
else
	ngx.say(reqErr);
	return ;
end

 

你可能感兴趣的:(nginx)