如何在tarantool卡式盒中执行热重装代码?

问题描述

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

解决方法

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

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

第一个可以通过卸载模块并再次加载来完成。所有模块在加载时都将其放置在“ package.loaded”表中。因此,您只需对其进行更新:

package.loaded['mymodule'] = nil
require('mymodule')

这是一种可以概括的低级方法:循环遍历“ 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)

如果重新加载mymodule.lua,而不再次调用router:route重新注册处理程序,则HTTP请求仍将调用旧函数。

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

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

实现此目标的第二种方法是使用cartridge-extensions,它允许您通过网络推送新代码。它已经具有一些优点,例如简化了与公共端点的绑定。