Управление конфигурацией в приложении Erlang - PullRequest
19 голосов
/ 03 июня 2011

Мне нужно распространять какую-то статическую конфигурацию через мое приложение. Как лучше всего это делать?

Я вижу три варианта:

  1. Вызывайте application:get_env напрямую всякий раз, когда модулю требуется получить значение конфигурации.
    • Плюс: проще, чем другие варианты.
    • Минус: как тестировать такие модули, не поднимая все приложение?
    • Минус: как запустить определенный модуль с другой конфигурацией (если требуется)?
  2. Передача конфигурации (полученной из application:get_env) модулям приложений во время запуска.
    • Plus: модули легче тестировать, вы можете запускать их с другой конфигурацией.
    • Минус: много шаблонного кода. Изменение формата конфигурации требует исправления нескольких мест.
  3. Удерживайте конфигурацию внутри отдельного процесса конфигурации.
    • Плюс: более-менее безопасное приближение. Проще отследить, где используется определенный параметр, и изменить эти места.
    • Минус: необходимо запустить процесс настройки перед запуском модулей.
    • Минус: как запустить определенный модуль с другой конфигурацией (если требуется)?

Ответы [ 5 ]

12 голосов
/ 03 июня 2011

Другой подход заключается в преобразовании данных конфигурации в исходный модуль Erlang, который делает данные конфигурации доступными через экспорт. Затем вы можете в любой момент изменить конфигурацию в работающей системе, просто загрузив новую версию модуля конфигурации.

10 голосов
/ 05 июня 2011

Для статической конфигурации в моих собственных проектах мне нравится опция (1). Я покажу вам шаги, которые я предпринимаю для доступа к параметру конфигурации с именем max_widgets в приложении с именем factory.

Сначала мы создадим модуль с именем factory_env, который содержит следующее:

-define(APPLICATION, factory).

get_env(Key, Default) ->
    case application:get_env(?APPLICATION, Key) of
        {ok, Value} -> Value;
        undefined -> Default
    end.

set_env(Key, Value) ->
    application:set_env(?APPLICATION, Key, Value).

Далее, в модуле, который должен прочитать max_widgets, мы определим макрос следующим образом:

-define(MAX_WIDGETS, factory_env:get_env(max_widgets, 1000)).

В этом подходе есть несколько приятных моментов:

  • Поскольку мы использовали application:set_env/3 и application:get_env/2, нам на самом деле не нужно запускать приложение factory, чтобы пройти наши тесты.
  • max_widgets получает значение по умолчанию, поэтому наш код будет работать, даже если параметр не определен.
  • Второй модуль может использовать другое значение по умолчанию для max_widgets.

Наконец, когда мы будем готовы к развертыванию, мы поместим файл sys.config в наш каталог priv и загрузим его с -config priv/sys.config во время запуска. Это позволяет нам изменять параметры конфигурации для каждого узла, если это необходимо. Это четко отделяет конфигурацию от кода - например, нам не нужно делать еще один коммит, чтобы изменить max_widgets на 500.

7 голосов
/ 03 июня 2011

Вы можете использовать процесс (возможно, gen_server?), Чтобы сохранить параметры конфигурации в его состоянии. Он должен предоставлять интерфейс get / set. Если значение не было задано явно, оно должно получить значение по умолчанию.

-export([get/1, set/2]).

...

get(Param) ->
  gen_server:call(?MODULE, {get, Param}).

...

handle_call({get, Param}, _From, State) ->
  case lookup(Param, State#state.params) of
    undefined ->
      application:get_env(...);
    Value ->
      {ok, Value}
  end.

...

Вы можете легко смоделировать этот модуль в своих тестах. Также будет легко обновить процесс с помощью новой конфигурации во время выполнения.

Вы можете использовать сопоставление с образцом и кортежи, чтобы связать разные параметры конфигурации с разными модулями:

set({ModuleName, ParamName}, Value) ->
  ...

get({ModuleName, ParamName}) ->
  ...

Поместите процесс в дерево контроля, чтобы он запускался до того, как все остальные процессы будут нуждаться в конфигурации.

О, я рад, что пока никто не предложил параметризованные модули :)

3 голосов
/ 03 июня 2011

Я бы сделал вариант 1 для статической конфигурации.Вы всегда можете проверить, установив параметры с помощью application:set_env/3,4.Причина, по которой вы хотите это сделать, заключается в том, что ваши тесты приложения должны будут все время запускать все приложение.А возможность настроить специфичную для теста конфигурацию в этот момент очень удобна.

Контроллер приложения работает по умолчанию, поэтому вам не нужно идти по пути приложения (вам нужно это сделатьв любом случае тоже!)

Наконец, если процесс нуждается в конкретной конфигурации, скажите это в данных конфигурации!Вы можете сохранить любой Erlang-термин, в частности, вы можете сохранить термин, который позволяет вам переопределять параметры конфигурации для определенного узла.используя gen_server или новейшие функции gproc, которые позволяют хранить такую ​​динамическую конфигурацию.

0 голосов
/ 09 апреля 2016

Я также видел, как люди используют .hrl (файл заголовка erlang), где вся конфигурация определена, и включают ее в начало любого файла, который нуждается в настройке.

Это делает для очень краткого поиска конфигурации, и вы получаете конфигурацию произвольной сложности.

Я полагаю, что вы также можете перезагрузить конфигурацию во время выполнения, выполнив горячую перезагрузку кода модуля. Недостатком является то, что если вы используете конфигурацию в нескольких модулях и перезагружаете только один из них, только этот модуль обновит свою конфигурацию.

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

...