Как я могу выполнить код горячей перезагрузки в картридже tarantool?

#tarantool #tarantool-cartridge

#tarantool #tarantool-картридж

Вопрос:

Как я могу выполнить код горячей перезагрузки в tarantool cartridge без перезапуска приложения?

Ответ №1:

Чтобы найти наилучшее решение вашей проблемы, важно понимать, чего вы пытаетесь достичь. Возможны 2 сценария:

  • Вы повторно развертываете свое приложение с помощью менеджера пакетов и вам необходимо перезагрузить код из файловой системы
  • Вы хотите отправить новый код через 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(). Смотрите, например, здесь. Чтобы повторно зарегистрировать обратные вызовы, вам нужно снова вызвать init() или apply_config() ваших ролей. Чтобы получить список ролей, вы можете использовать cartridge.roles.get_known_roles() . Вам нужно перебрать их и повторно инициализировать.

Чтобы вызвать функцию, которая перезагружает код, вам нужно либо подключиться через двоичный протокол, либо использовать admin socket. Сокет администратора позволяет вам написать простой сценарий оболочки для этого. Вы можете получить представление, посмотрев на скрипт tarantool_is_up . Он демонстрирует подход, который вы можете адаптировать для своего варианта использования.

Второй способ добиться этого — использовать расширения для картриджей, которые позволяют передавать новый код по сети. В нем уже есть некоторые тонкости, такие как упрощенная привязка к общедоступным конечным точкам.