【问题标题】:nginx lua make an external http call without blocking the requestnginx lua 在不阻塞请求的情况下进行外部 http 调用
【发布时间】:2017-04-12 19:31:23
【问题描述】:

当某些情况发生时,我们需要将事件从 nginx 记录到我们的事件服务器。我知道我可以使用 access_by_lua 进行 http 调用。由于事件记录可能会失败或需要更长时间,因此我们不希望请求处理以等待 http 操作完成。

如果我使用 lua 访问,记录所需的时间将被添加到请求时间中。

有没有办法在异步过程中启动事件记录过程,以便请求可以继续,而事件记录可能需要时间。

【问题讨论】:

  • 您好,您找到真正的解决方案了吗?

标签: nginx lua


【解决方案1】:

您可以在 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() 进行日志记录。但请记住 - 它是完全缓冲的解决方案。
  • 谢谢,我试试看。
【解决方案2】:

我不在 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多