Хранение вложенных таблиц в общей памяти nginx

Я работаю с open-resty и lua, чтобы создать сервер для перенаправления запросов. Перенаправления выполняются на основе некоторых данных из структуры дерева данных lua (вложенные таблицы).

Я ищу способ заполнить эти данные один раз при запуске, а затем поделиться данными между работниками.

ngx.ctx может сохранять произвольные данные, но сохраняется только во время запроса. Shared dict длится до конца, но может сохранять только список примитивов.

Я читал, что можно обмениваться данными между модулями lua. Потому что модули создаются только один раз при запуске. Код примерно такой

local _M = {}

local data = {
    dog = {"value1", "value4"},
    cat = {"value2", "value5"},
    pig = {"value3", "value6"}
}


function _M.get_age(name)
    return data[name]
end

return _M

а потом в nginx.conf

location /lua {
    content_by_lua_block {
        local mydata = require "mydata"
        ngx.say(mydata.get_age("dog"))
    }
}

Потокобезопасна ли эта третья возможность? Есть ли что-то еще, что может достичь этого?

Документации по этому поводу не так много, поэтому разместил ее здесь. Любая информация поможет, спасибо


person regenbar    schedule 07.06.2019    source источник


Ответы (1)


Вы можете заполнить свои данные в init_by_lua и получить к ним доступ позже. В вашем случае инициализация модуля mydata может быть достигнута следующим образом:

init_by_lua_block {
     require "mydata"
}

init_by_lua запускается один раз при запуске nginx, а затем процесс, который он запускает, разветвляется на воркеры, поэтому каждый из них содержит независимую копию этих данных.

Воркеры однопоточные, поэтому вы можете безопасно получить доступ к своим данным.


Теперь, если вы хотите изменить свою конфигурацию во время выполнения, не перезагружая nginx, это становится немного сложнее. Каждый воркер независим, но мы можем использовать ngx.shared.DICT для распространения изменения. В зависимости от ваших требований есть два решения, которые вы можете использовать:

  1. После каждого изменения помещайте вашу конфигурацию в общий словарь. Создайте таймер, который периодически перезагружает конфигурацию рабочего процесса из этого общего кеша.
  2. После каждого изменения помещайте свою конфигурацию в общий словарь вместе с текущей меткой времени или номером версии. По каждому запросу в рабочем потоке проверяйте, не отличается ли эта временная метка/версия от той, что кэширована локально, - если это так, то десериализуйте эту конфигурацию и кэшируйте ее локально.

Если у вас есть API, который можно использовать, вы можете использовать lua-resty-lock. для создания сквозных критических секций, которые синхронизируют модификацию.

person piotrp    schedule 08.06.2019
comment
Спасибо за ответ. Это помогает, и я могу это использовать. Таким образом, это будет означать, что если я захочу обновить дату, мне придется перезагрузить nxing. И еще одно, мне интересно ваше мнение. Не могли бы вы взглянуть на это. Только абзац под названием «Экземпляры модулей» с кодом. (kiki.to/blog/2014/04/ 11/rule-4-make-stateless-modules) Будет ли это лучшим решением? Я хотел бы иметь возможность создавать, обновлять, удалять значения из основных данных и чтобы все рабочие могли получить к ним доступ. - person regenbar; 09.06.2019
comment
Я расширил свой ответ, чтобы покрыть изменение ваших данных. Модули хороши тем, что позволяют сделать ваш код читабельным, так что смело используйте их. - person piotrp; 10.06.2019
comment
Данные хранятся во вложенной таблице и являются общими. DICT не принимает сложные данные, такие как вложенные таблицы. Общий дикт может сохранить карту, но только если ключи и значения примитивны. Однако у вас есть хорошая мысль, у меня может быть сериализованная строка и версия в общем диктовке. Таймер может инициировать рабочие процессы для десериализации данных и их использования. Спасибо - person regenbar; 10.06.2019
comment
cjson должен быть в порядке для сериализации ваших данных - person piotrp; 10.06.2019