nginx lua实现异步外部http请求

当某些条件达成时,我们需要在nginx中向事件服务器记录事件。我知道可以使用access_by_lua来进行http调用。然而,如果记录事件失败或者时间较长,我们不想让请求等待直到这个http操作完成。

如果使用access by lua,记录事件的时间将会计入请求时间中。

有没有一种方法可以启动异步事件记录进程,以便请求可以在此之后继续而事件记录可以耗费它的时间。

点赞
用户2328287
用户2328287

我没有在 nginx 上尝试过它。但是在我的应用程序中,我使用单独的线程来处理所有 IO,并使用 ZeroMQ 库进行通信。

根据文档,您可以在 init_by_lua_block 中创建/运行具有通信套接字的工作线程,然后在其他部分中使用它。但为了做到这一点,您应该记住,如果请求/秒不断大于写入/秒,那么最终可能会导致内存不足。使用 ZeromMQ 可以轻松地创建多个工作线程。当然,在这种情况下,工作线程无法访问 nginx 模块。

但您可以使用例如 LuaSocket 或 Lua-cURL(后者可用于在异步模式下执行多个请求)。

单线程的基本模板。

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
2017-04-11 09:17:47
用户2060502
用户2060502

你可以在 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()  -- 良好编写的 HTTP 客户端将在此关闭连接
         -- 在此处访问 MySQL、PostgreSQL、Redis、Memcached 等
     }
 }
2017-04-12 11:31:23