lua-resty-load
为 ngx_lua 动态加载 Lua 文件/脚本
$ opm get huangnauh/lua-resty-load
名称
lua-resty-load - 为 ngx_lua 动态加载 Lua 文件/脚本
状态
此库已经可以使用,但仍处于实验阶段。
Lua API 仍在不断变化,可能在不久的将来发生改变。
描述
这个 Lua 库帮助 OpenResty/ngx_lua 用户动态加载 Lua 文件/脚本。
需要注意的是,动态加载的 Lua 代码不应该使用 FFI API 定义新的 C 符号或 C 类型。
注意,至少需要 ngx_lua v0.7.18
概要
http {
lua_package_path "/path/to/lua-resty-load/lib/?.lua;;";
init_by_lua '
local rload = require "resty.load"
rload.init()
-- if you need code to be loaded in the beginning
-- please provide the module with following interfaces:
--
--
-- local load_init_module = require "load_init_module_name"
-- local load_init = load_init_module:new()
-- local keys = load_init:lkeys()
--
-- for _, key in ipairs(keys) do
-- local code = load_init:lget(key)
-- print("script/module name: ", key, ", code: ", code)
-- end
--
--
-- then just pass the name to rload.init:
-- local rload = require "resty.load"
-- rload.init({module_name="load_init_module_name"})
';
init_worker_by_lua '
local rload = require "resty.load"
rload.create_load_syncer()
';
}
server {
location /test {
content_by_lua '
local rload = require "resty.load"
rload.set_code("script.abc", "local test = require \'modules.abc\' ngx.say(\'version: \',test.version)")
rload.set_code("modules.abc", "local _M = {version = 0.01} return _M")
rload.install_code()
local test = require "script.abc"
test()
-- dynamic load
rload.set_code("script.abc", "ngx.say(\'hello world\')")
rload.install_code("script.abc")
local test = require "script.abc"
test()
';
}
}
方法
init
语法: ok, err = load.init(options_config?)
上下文: init_by_lua*
初始化库。如果失败,则返回 `nil` 和一个描述错误的字符串。
如果您需要在开始时加载任何代码,可以通过定义一个自定义的 load_init 模块来实现。
可以将一个可选的 Lua 表格 `options_config` 作为此方法的唯一参数指定,以指定 load_init 模块配置。
模块名称
您的 load_init 模块必须实现 new()、lkeys() 和 lget(key) 方法,以及可选的 lversion() 方法。
名称 ====
lua-resty-load - 为 ngx_lua 动态加载 Lua 文件/脚本
目录 =================
* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [init](#init) * [create_load_syncer](#create_load_syncer) * [set_code](#set_code) * [install_code](#install_code) * [load_script](#load_script) * [get_load_version](#get_load_version) * [get_version](#get_version) * [作者](#author) * [版权和许可](#copyright-and-license)
状态 ======
此库已经可以使用,但仍处于实验阶段。
Lua API 仍在不断变化,可能在不久的将来发生改变。
描述 ===========
这个 Lua 库帮助 OpenResty/ngx_lua 用户动态加载 Lua 文件/脚本。
需要注意的是,动态加载的 Lua 代码不应该使用 FFI API 定义新的 C 符号或 C 类型。
注意,至少需要 [ngx_lua v0.7.18](https://github.com/openresty/lua-nginx-module/tags)
概要 ========
```lua http { lua_package_path "/path/to/lua-resty-load/lib/?.lua;;";
init_by_lua '
local rload = require "resty.load"
rload.init()
-- if you need code to be loaded in the beginning
-- please provide the module with following interfaces:
--
--
-- local load_init_module = require "load_init_module_name"
-- local load_init = load_init_module:new()
-- local keys = load_init:lkeys()
--
-- for _, key in ipairs(keys) do
-- local code = load_init:lget(key)
-- print("script/module name: ", key, ", code: ", code)
-- end
--
--
-- then just pass the name to rload.init:
-- local rload = require "resty.load"
-- rload.init({module_name="load_init_module_name"})
';
init_worker_by_lua '
local rload = require "resty.load"
rload.create_load_syncer()
';
}
server {
location /test {
content_by_lua '
local rload = require "resty.load"
rload.set_code("script.abc", "local test = require \'modules.abc\' ngx.say(\'version: \',test.version)")
rload.set_code("modules.abc", "local _M = {version = 0.01} return _M")
rload.install_code()
local test = require "script.abc"
test()
-- dynamic load
rload.set_code("script.abc", "ngx.say(\'hello world\')")
rload.install_code("script.abc")
local test = require "script.abc"
test()
';
}
}
```
[返回目录](#table-of-contents)
方法 =======
[返回目录](#table-of-contents)
init ------- `语法: ok, err = load.init(options_config?)`
`上下文: init_by_lua*`
初始化库。如果失败,则返回 `nil` 和一个描述错误的字符串。
如果您需要在开始时加载任何代码,可以通过定义一个自定义的 load_init 模块来实现。
可以将一个可选的 Lua 表格 `options_config` 作为此方法的唯一参数指定,以指定 load_init 模块配置。
* `模块名称`
Your load_init module must implement the new(), lkeys() and lget(key) methods, along with the optional method lversion().
* [new](#load_init_modulenew)
* [lkeys](#load_init_modulelkeys)
* [lget](#load_init_modulelget)
* [lversion](#load_init_modulelversion)
load_init_module:new --- 创建一个 load_init 对象。如果失败,则返回 nil 和一个描述错误的字符串。
* `options_config`
Just the parameter in `load.init`
load_init_module:lkeys --- **语法:** *keys, err = load_init_module:lkeys()*
检索包含所有脚本/模块名称的 Lua 数组。如果失败,则返回 nil 和一个描述错误的字符串。
load_init_module:lget --- **语法:** *code, err = load_init_module:lget(key)*
检索脚本/模块名称为 `key` 的代码。如果失败,则返回 nil 和一个描述错误的字符串。
load_init_module:lversion --- **语法:** *version, err = load_init_module:lversion()*
检索当前代码的版本。这对于回退和版本检查是可选的。`version` 不超过 32 个字符。
如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
create_load_syncer -------
`语法: ok, err = rload.create_load_syncer()`
`上下文: init_worker_by_lua*`
创建一个 Nginx 定时器,以使动态加载工作。如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
set_code ------- `语法: ok, err = rload.set_code(name, code)`
将代码设置为模块 `name`,但它还没有生效。如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
install_code ------- `语法: ok, err = rload.install_code(name?)`
默认情况下,所有设置的代码都将被安装。在 load_syncer 定时器被调用后,它将生效。
当给出 `name` 参数时,只有模块 `name` 将被安装。
如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
load_script ------- `语法: fun, err = rload.load_script(name, options_table?)`
按名称 `name` 加载脚本,此方法返回(成功)脚本函数 `fun` 以备后用。
可以将一个可选的 Lua 表格作为此方法的最后一个参数指定,以指定脚本的环境。
* `env`
If this option is set to a table, then a function environment will be set.
* `global`
If this option is set to `true`, then the global environment will be set.
如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
get_load_version ------- `语法: commit_version, err = rload.get_load_version()`
此方法返回如果 `load_init_module` 具有 `lversion` 方法的值,或者默认情况下返回 "0"。
如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
get_version ------- `语法: ok, err = rload.get_version()`
返回结果 JSON 字符串,例如:
``` { "global_version": 4, "commit_version": "79630b", "modules": [ { "time": "2016-11-23 17:38:11", "version": "aed4a968ef14f8db732e3602c34dc37a", "name": "modules.abc" }, { "time": "2016-11-23 17:38:11", "version": "7a170b7731543b56722101c4167965b3", "name": "script.test" } ] } ```
* `global_version`
Returns how many times the lua library loads script/module since nginx start/reload
* `commit_version`
Returns the exactly the same version as [get_load_version](#get_version).
* `version`
Returns the MD5 hash of the code.
如果失败,则返回 nil 和一个描述错误的字符串。
[返回目录](#table-of-contents)
作者 ======
UPYUN Inc.
[返回目录](#table-of-contents)
版权和许可 =====================
此模块根据 BSD 许可证授权。
版权所有 (C) 2016,由 UPYUN Inc.
保留所有权利。
在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用此软件,无论是否修改:
* 源代码的重新分发必须保留上述版权声明、此条件列表以及以下免责声明。
* 二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表以及以下免责声明。
本软件由版权持有人和贡献者“按现状”提供,任何明示或暗示的担保,包括但不限于对适销性和特定用途适用性的暗示担保均被免除。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、示例性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论其责任形式如何,无论是在合同、严格责任或侵权行为(包括疏忽或其他原因)的情况下,无论是否因使用本软件而产生,即使已被告知可能发生此类损害。
[返回目录](#table-of-contents) new lkeys lget lversion
load_init_module:new
创建一个 load_init 对象。如果失败,则返回 nil 和一个描述错误的字符串。
options_config
只是 `load.init` 中的参数。
load_init_module:lkeys
语法: keys, err = load_init_module:lkeys()
检索包含所有脚本/模块名称的 Lua 数组。如果失败,则返回 nil 和一个描述错误的字符串。
load_init_module:lget
语法: code, err = load_init_module:lget(key)
检索脚本/模块名称为 `key` 的代码。如果失败,则返回 nil 和一个描述错误的字符串。
load_init_module:lversion
语法: version, err = load_init_module:lversion()
检索当前代码的版本。这对于回退和版本检查是可选的。`version` 不超过 32 个字符。
如果失败,则返回 nil 和一个描述错误的字符串。
create_load_syncer
语法: ok, err = rload.create_load_syncer()
上下文: init_worker_by_lua*
创建一个 Nginx 定时器,以使动态加载工作。如果失败,则返回 nil 和一个描述错误的字符串。
set_code
语法: ok, err = rload.set_code(name, code)
将代码设置为模块 `name`,但它还没有生效。如果失败,则返回 nil 和一个描述错误的字符串。
install_code
语法: ok, err = rload.install_code(name?)
默认情况下,所有设置的代码都将被安装。在 load_syncer 定时器被调用后,它将生效。
当给出 `name` 参数时,只有模块 `name` 将被安装。
如果失败,则返回 nil 和一个描述错误的字符串。
load_script
语法: fun, err = rload.load_script(name, options_table?)
按名称 `name` 加载脚本,此方法返回(成功)脚本函数 `fun` 以备后用。
可以将一个可选的 Lua 表格作为此方法的最后一个参数指定,以指定脚本的环境。
env
如果此选项设置为表格,则将设置函数环境。
global
如果此选项设置为 `true`,则将设置全局环境。
如果失败,则返回 nil 和一个描述错误的字符串。
get_load_version
语法: commit_version, err = rload.get_load_version()
此方法返回如果 `load_init_module` 具有 `lversion` 方法的值,或者默认情况下返回 "0"。
如果失败,则返回 nil 和一个描述错误的字符串。
get_version
语法: ok, err = rload.get_version()
返回结果 JSON 字符串,例如:
{
"global_version": 4,
"commit_version": "79630b",
"modules": [
{
"time": "2016-11-23 17:38:11",
"version": "aed4a968ef14f8db732e3602c34dc37a",
"name": "modules.abc"
},
{
"time": "2016-11-23 17:38:11",
"version": "7a170b7731543b56722101c4167965b3",
"name": "script.test"
}
]
}
global_version
返回自 nginx 启动/重新加载以来 Lua 库加载脚本/模块的次数。
commit_version
返回与 get_load_version 完全相同的版本。
version
返回代码的 MD5 哈希值。
如果失败,则返回 nil 和一个描述错误的字符串。
作者
UPYUN Inc.
版权和许可
此模块根据 BSD 许可证授权。
版权所有 (C) 2016,由 UPYUN Inc.
保留所有权利。
在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用此软件,无论是否修改:
源代码的重新分发必须保留上述版权声明、此条件列表以及以下免责声明。
二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表以及以下免责声明。
本软件由版权持有人和贡献者“按现状”提供,任何明示或暗示的担保,包括但不限于对适销性和特定用途适用性的暗示担保均被免除。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、示例性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论其责任形式如何,无论是在合同、严格责任或侵权行为(包括疏忽或其他原因)的情况下,无论是否因使用本软件而产生,即使已被告知可能发生此类损害。
作者
huangnauh huanglibo2010@gmail.com
许可证
2bsd
版本
-
为 ngx_lua 动态加载 Lua 文件/脚本 2017-11-15 08:56:38