當發生某些情況時,我們需要從nginx將事件記錄到我們的事件服務器。我知道我可以使用access_by_lua進行http調用。由於事件記錄可能會失敗或需要更長時間,因此我們不希望請求處理等待http操作完成。nginx lua在不阻止請求的情況下進行外部http調用
如果我使用lua訪問,記錄所花費的時間將被添加到請求時間。
有沒有辦法在異步過程中啓動事件日誌記錄過程,以便請求可以繼續前進,而事件日誌記錄可能需要時間。
當發生某些情況時,我們需要從nginx將事件記錄到我們的事件服務器。我知道我可以使用access_by_lua進行http調用。由於事件記錄可能會失敗或需要更長時間,因此我們不希望請求處理等待http操作完成。nginx lua在不阻止請求的情況下進行外部http調用
如果我使用lua訪問,記錄所花費的時間將被添加到請求時間。
有沒有辦法在異步過程中啓動事件日誌記錄過程,以便請求可以繼續前進,而事件日誌記錄可能需要時間。
我不試試在nginx上。但在我的應用程序中,我使用單獨的線程來執行所有IO並使用ZeroMQ庫與它進行通信。 根據文檔,您可以使用init_by_lua_block
中的通信套接字創建/運行工作線程,然後在其他部分使用它。但要做到這一點,你應該記住,如果請求/秒總是大於寫入/秒,那麼最終可能會導致內存不足。另外與ZeromMQ很容易做出幾個工作線程。當然,在這種情況下,工作線程對nginx模塊沒有訪問權限。 但您可以使用例如LuaSocket或Lua-cURL(最後一個可用於在異步模式下執行多個請求)。 單線程基本sceleton。
local thread = function(actor)
local msg, err while true do
msg, err = actor:recvx()
if not msg then break end
print(msg)
end
print('Close thread: ', tostring(err))
end
local zthreads = require "lzmq.threads"
local ztimer = require "lzmq.timer"
local actor = zthreads.xactor(thread):start()
for i = 1, 10 do
actor:send(string.format('message #%d', i))
ztimer.sleep(1000)
end
可以content_by_lua_內做你平常的處理*和明確ngx.eof()
所以HTTP請求將無延遲地處理指定響應輸出流的末尾。
之後,你可以做任何你想要的,使用cosocket API或ngx.location.capture()例如
https://github.com/openresty/lua-nginx-module#ngxeof
下面是從文檔例如:
location = /async {
keepalive_timeout 0;
content_by_lua_block {
ngx.say("got the task!")
ngx.eof() -- well written HTTP clients will close the connection at this point
-- access MySQL, PostgreSQL, Redis, Memcached, and etc here...
}
}
謝謝亞歷山大。不幸的是,我沒有提供lua的內容,內容由上游後端提供。任何解決方法? –
爲上游創建一個單獨的位置,並在content_by_lua_ *中使用ngx.location.capture()。它需要更多的編程才能將所有頭文件和主體傳遞迴客戶端,但在正常的請求處理完成時,將允許使用cosocket API或ngx.location.capture()作爲日誌記錄目的。但請記住 - 它是全緩衝解決方案。 –
謝謝,我會試試看。 –
嗨,你找到任何真正的解決方案? –