【问题标题】:How do you initialize mnesia on production?您如何在生产中初始化 mnesia?
【发布时间】:2016-08-16 15:25:36
【问题描述】:

我正在使用 rebar3 来生成版本,但是如何在生产中初始化 mnesia?

如果我编写一个执行 mnesia:create_schema([node()]) 的“安装”escript - 它将使用与发布使用的节点名称完全不同的节点名称。

所以我最终为“nonode@nonode”创建了一个模式,而当我使用my-app-1.0.0 start 启动我的应用程序时,生产 mnesia 尝试访问“myapp@localhost”节点。

而且,这是一个先有鸡还是先有蛋的问题:

  1. 如果没有 mnesia 表,我无法启动我的应用程序
  2. 如果没有运行我的应用程序,我无法安装我的 mnesia 表(与应用程序将使用的 node() 名称相同)。

如果有什么好的方法可以解决这个问题?

这是我独立运行的安装脚本:

#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable ls-mnesia debug verbose
-include("../include/rr.hrl").

main(_) ->
    application:set_env(mnesia, dir, "/usr/local/src/db/mnesia"),
    application:stop(mnesia),
    install([node()|nodes()]).

install(Nodes) ->
    case mnesia:create_schema(Nodes) of
        ok -> 
            rpc:multicall(Nodes, application, start, [mnesia]),
            read_store_create_tables(Nodes),
            event_store_create_tables(Nodes),
            rpc:multicall(Nodes, application, stop, [mnesia]);
        Err -> 
            error_logger:warning_msg("Could not create schema: ~p~n", [Err]),
            Err
    end.    

event_store_create_tables(Nodes) ->
    {_, ok} = mnesia:create_table(rr_events,
            [{attributes, record_info(fields, rr_events)},
             {disc_copies, Nodes},
             {type, bag}]).

read_store_create_tables(Nodes) ->
    % Initialize the actual data-tables for the projections
    {_, ok} = mnesia:create_table(rr_competencies,
            [{attributes, record_info(fields, rr_competencies)},
             {disc_copies, Nodes}]).

P.S.:我正在使用 rebar3,它使用 relx 来构建版本。

【问题讨论】:

    标签: erlang mnesia rebar3


    【解决方案1】:

    我使用我自己的build system,主要是因为这个确切的要求——能够在启动之前安装和初始化节点。这个想法很简单:有two releases,在这个特殊的例子中称为cmdhumbundeecmd 版本不会启动主要应用程序,只会加载它们。然后执行一个特殊函数来初始化节点。该函数在reltool.config 文件中配置。在这种情况下,它是来自deploy 应用程序的hbd_setup。该函数读取配置文件并从备份创建和初始化 mnesia 数据库,或者如果备份不存在则创建一个新数据库。一旦安装了节点,它就会使用正确的版本启动。在开发(直接从源代码)和生产(从 OTP 版本)中执行相同的步骤。

    通过该设置,您描述的问题不存在,因为两个版本都是从同一位置启动,使用几乎相同的命令和配置文件(builderlreltool.config 中的配置生成它们)。


    您可以通过手动或使用某种脚本执行这些步骤,对任何构建工具(包括 rebar3relx)采用相同的想法。

    builderl 所做的是它自动执行这些步骤并提供一个环境以在开发和生产中以相同的方式执行它们,例如查看bottom of the humbundee project's README 文件:

    安装节点。这将启动cmd发布并执行hbd_setup:install/2函数来初始化节点:

    ./bin/init.esh
    

    启动节点。这将启动humbundee 版本,它会启动所有应用程序及其相应的主管树:

    ./bin/start.esh
    

    builderl 实际上使用rebar 来拉取和编译dependencies that depend on other projects,但是它只使用 OTP 来创建发布。它还可以使用project-wide dependency file 自己下载依赖项,然后是compiled with make(没有make 的编译是work in progress)。我希望这会有所帮助。

    【讨论】:

    • 但是您如何处理通过构建脚本(即 ansible)使这一切自动化?问题在于应用程序在启动时不像脚本,它作为服务运行 - 因此脚本不知道应用程序何时完成初始化数据库。 (哇,这比我想象的要复杂得多。)
    • 请查看这个答案(搜索init:stop()):stackoverflow.com/questions/36359040/… 然后这个函数:github.com/yoonka/builderl/blob/master/src/bld_init.erl#L902 基本上有两个Erlang实例。执行 ./bin/init.esh 时,builderl 在自己的 VM 中运行。然后它使用cmd 版本启动已安装的VM,对其进行配置,然后将其关闭。如果出现问题,它会返回代码1。当builderl 完成时,它的返回码可以被make 或其他脚本检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 2016-03-08
    • 2021-07-29
    • 2012-05-10
    相关资源
    最近更新 更多