如何在 tarantool 墨盒中执行热重载代码?

Ale*_*aev 3 tarantool tarantool-cartridge

如何在tarantool cartridge不重新启动应用程序的情况下执行热重载代码?

小智 6

为了找到问题的最佳解决方案,了解您要实现的目标很重要。有两种可能的情况:

  • 您使用包管理器重新部署您的应用程序,并需要从文件系统重新加载代码
  • 您想通过网络 API 通过数据库 API 推送新代码

第一个可以通过卸载模块并再次加载来完成。所有模块在加载时都将自己放置到“package.loaded”表中。所以你只需要更新它:

package.loaded['mymodule'] = nil
require('mymodule')
Run Code Online (Sandbox Code Playgroud)

这是一种可以概括的低级方法:循环遍历 'package.loaded' 的内容,卸载所有内容并重新加载。您需要小心不要卸载文件系统上不存在的模块。有一个模块可以帮助您解决这个问题:https : //github.com/moonlibs/package-reload

虽然该模块将帮助您掌握基础知识,但您还需要考虑其他事项。在 Lua 中,很容易在全局对象中存储函数指针。如果您重新加载函数本身,您将不会神奇地更新所有具有指向旧函数的指针的位置。例如,让我们考虑 http 服务器:

-- in mymodule.lua
local function handler(req)
    local resp = req:render({text = req.method..' '..req.path })
    resp.headers['x-test-header'] = 'test';
    resp.status = 201
    return resp
end

-- somewhere else
router:route({ path = '/test', method = 'GET' }, mymodule.handler)
Run Code Online (Sandbox Code Playgroud)

如果你重新加载 mymodule.lua,并且没有再次调用 router:route 来重新注册处理程序,HTTP 请求仍然会调用旧函数。

在墨盒中,您通常在 apply_config() 或 init() 中注册函数。例如,请参见此处。为了重新注册回调,您需要再次调用角色的 init() 或 apply_config()。要获取角色列表,您可以使用Cartridge.roles.get_known_roles()。您需要遍历它们并重新初始化它们。

为了调用重新加载代码的函数,您需要通过二进制协议进行连接,或者使用管理套接字。管理套接字允许您为此编写一个简单的 shell 脚本。您可以通过查看tarantool_is_up 脚本来了解这个想法。它演示了您可以适应您的用例的方法。

实现此目的的第二种方法是使用允许您通过网络推送新代码的盒式扩展。它已经有一些优点,比如简化了对公共端点的绑定。