管理Erlang应用程序中的配置

Iva*_*rov 19 erlang configuration

我需要通过我的应用程序分发某种静态配置.这样做的最佳做法是什么?

我看到三个选择:

  1. application:get_env只要模块需要获取配置值,就直接调用.
    • 另外:比其他选项更简单.
    • 减:如何测试这些模块而不需要整个应用程序?
    • 减:如何启动具有不同配置的某些模块(如果需要)?
  2. application:get_env在启动期间将配置(从中检索)传递给应用程序模块.
    • 另外:模块更容易测试,您可以使用不同的配置启动它们.
    • 减:很多样板代码.更改配置格式需要修复多个位置.
  3. 将配置保持在单独的配置过程中.
    • 另外:或多或少类型安全的approch.更容易跟踪使用某些参数的位置并更改这些位置.
    • 减:在运行模块之前需要调出配置过程.
    • 减:如何启动具有不同配置的某些模块(如果需要)?

Gre*_*ill 12

另一种方法是将配置数据转换为Erlang源模块,通过导出使配置数据可用.然后,您只需加载新版本的配置模块,即可在运行的系统中随时更改配置.

  • 您可以使用[meck](https://github.com/eproxus/meck)在测试期间创建模拟模块(无耻的自我插件,我是作者),或参数化代码中的模块名称(这是真的整洁的测试). (3认同)

Dav*_*don 10

对于我自己项目中的静态配置,我喜欢选项(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).
Run Code Online (Sandbox Code Playgroud)

接下来,在需要阅读的模块中,max_widgets我们将定义如下的宏:

-define(MAX_WIDGETS, factory_env:get_env(max_widgets, 1000)).
Run Code Online (Sandbox Code Playgroud)

这种方法有一些好处:

  • 由于我们使用application:set_env/3application:get_env/2,我们实际上并不需要启动factory以应用有我们的测试通过.
  • max_widgets 获取默认值,因此即使未定义参数,我们的代码仍然可以工作.
  • 第二个模块可以使用不同的默认值max_widgets.

最后,当我们准备好部署时,我们将把sys.config文件放在我们的priv目录中并-config priv/sys.config在启动期间加载它.这允许我们根据需要在每个节点上更改配置参数.这将配置与代码完全分开 - 例如,我们不需要再次提交以更改max_widgets为500.


Rob*_*loi 7

您可以使用进程(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.

...
Run Code Online (Sandbox Code Playgroud)

然后,您可以在测试中轻松模拟此模块.在运行时使用一些新配置更新过程也很容易.

您可以使用模式匹配和元组将不同的配置参数关联到不同的模块:

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

get({ModuleName, ParamName}) ->
  ...
Run Code Online (Sandbox Code Playgroud)

将该过程置于监督树下,因此它将在所有其他需要配置的过程之前启动.

哦,我很高兴到目前为止没有人建议参数化模块 :)