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

 

發佈了109 篇原創文章 · 獲贊 16 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章