在nginx共享内存中存储嵌套表

我正在使用open-resty和lua创建一个用于重定向请求的服务器。重定向是基于来自lua数据树结构(嵌套表)的一些数据完成的。

我正在寻找一种方法来在启动时仅填充一次这些数据,并在此后在worker之间共享数据。

ngx.ctx可以保存任意数据,但仅在请求期间持续。 共享字典一直持续到结束,但只能保存原始列表。

我读过可以跨lua模块共享数据的文章。因为模块仅在启动时实例化。代码类似于以下内容

local _M = {}

local data = {
    dog = {"value1", "value4"},
    cat = {"value2", "value5"},
    pig = {"value3", "value6"}
}

function _M.get_age(name)
    return data[name]
end

return _M

然后在nginx.conf中

location /lua {
    content_by_lua_block {
        local mydata = require "mydata"
        ngx.say(mydata.get_age("dog"))
    }
}

这第三种可能性是线程安全的吗? 还有其他能够实现这一点的东西吗?

这方面的文档不是很多,因此在此发布。任何信息都会有所帮助, 谢谢

点赞
用户369550
用户369550

你可以在 init_by_lua 中填充数据,并在以后访问它。在你的例子中,mydata 模块的初始化可以通过以下方式实现:

init_by_lua_block {
     require "mydata"
}

init_by_lua 在 Nginx 启动时运行一次,然后它运行的进程会分叉为 worker,因此每个 worker 包含该数据的独立副本。

workers 是单线程的,所以你可以安全地访问你的数据。


现在,如果你想在不重新加载 Nginx 的情况下在运行时修改你的配置,那么就会变得有些复杂。每个 worker 是独立的,但我们可以使用 ngx.shared.DICT 来传播更改。根据你的需求,有两种解决方案可以使用:

  1. 在每次更改后,将你的配置放入共享字典中。创建一个定时器,定期从该共享缓存中重新加载 worker 的配置。
  2. 在每次更改后,将你的配置与当前时间戳和版本号一起放入共享字典中。在每个 worker 的每个请求中检查是否比本地缓存的时间戳/版本号还要新 - 如果是,则将此配置反序列化并将其缓存到本地。

如果你有一个可用的 API,那么可以使用 lua-resty-lock 来创建跨 worker 的关键部分,以同步修改。

2019-06-08 20:32:39