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 库加载脚本/模块的次数。

  • version

    返回代码的 MD5 哈希值。

如果失败,则返回 nil 和一个描述错误的字符串。

作者

UPYUN Inc.

版权和许可

此模块根据 BSD 许可证授权。

版权所有 (C) 2016,由 UPYUN Inc.

保留所有权利。

在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用此软件,无论是否修改:

  • 源代码的重新分发必须保留上述版权声明、此条件列表以及以下免责声明。

  • 二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表以及以下免责声明。

本软件由版权持有人和贡献者“按现状”提供,任何明示或暗示的担保,包括但不限于对适销性和特定用途适用性的暗示担保均被免除。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、示例性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论其责任形式如何,无论是在合同、严格责任或侵权行为(包括疏忽或其他原因)的情况下,无论是否因使用本软件而产生,即使已被告知可能发生此类损害。

作者

huangnauh huanglibo2010@gmail.com

许可证

2bsd

版本