【问题标题】:Upgrading a riak_core application with relup使用 relup 升级 riak_core 应用程序
【发布时间】:2017-04-18 14:04:19
【问题描述】:

我正在尝试在运行时升级 riak_core erlang 应用程序。

简单的升级正在运行。我使用 rebar3 和 relflow 成功升级了应用程序。但是,如果我更改 vnode 的内部结构并使用 relflow 和 rebar3 relup 生成新版本,则 vnode 将停止工作。 vnode 被称为“cavv”。

热升级后,此时崩溃:

DocIdx = riak_core_util:chash_key({<<"run">>, term_to_binary(os:timestamp())}), 

导致此错误:

** exception error: bad argument
     in function  lists:keyfind/3
        called as lists:keyfind(chash_keyfun,1,[{name,<<"run">>}|undefined])
     in call from riak_core_util:chash_key/2 (_build/default/lib/riak_core/src/riak_core_util.erl, line 266)
     in call from cavv_vnode:run/0 (_build/prod/lib/cavv/src/cavv_vnode.erl, line 38)

我的 relup 看起来像这样:

{"0.1.2",
 [{"0.1.1",[],
   [{load_object_code,{cavv,"20161203-211601-relflow",[cavv_vnode]}},
    point_of_no_return,
    {load,{cavv_vnode,brutal_purge,brutal_purge}}]}],
 [{"0.1.1",[],[point_of_no_return]}]}. 

我错过了什么吗?我是否必须重新启动一些主 vnode?我尝试重新启动一些主管,但没有成功。

查看riak_core的源码:

%% @spec chash_key(BKey :: riak_object:bkey()) -> chash:index()
%% @doc Create a binary used for determining replica placement.
chash_key({Bucket,_Key}=BKey) ->
    BucketProps = riak_core_bucket:get_bucket(Bucket),
    chash_key(BKey, BucketProps).

%% @spec chash_key(BKey :: riak_object:bkey(), [{atom(), any()}]) ->
%%          chash:index()
%% @doc Create a binary used for determining replica placement.
chash_key({Bucket,Key}, BucketProps) ->
    {_, {M, F}} = lists:keyfind(chash_keyfun, 1, BucketProps), %% <-- Line 266
    M:F({Bucket,Key}).

我试图了解正在发生的事情,但很难掌握正在发生的事情。 BucketProps 中的某些东西是 undefined 升级后不应该 undefined 什么?

当我重新启动整个应用程序时,它就像一个魅力。

我在使用 riak_core 进行热升级时是否遗漏了什么?还是直接关闭整个节点,然后升级并重新启动它,忘记热代码升级更好?

更新 与此同时,我发现 riak_core_bucket 出了点问题。

运行以下命令:riak_core_bucket:get_bucket(&lt;&lt;"run"&gt;&gt;).

升级前:

[{name,<<"run">>},
 {allow_mult,false},
 {basic_quorum,false},
 {big_vclock,50},
 {chash_keyfun,{riak_core_util,chash_std_keyfun}},
 {dvv_enabled,false},
 {dw,quorum},
 {last_write_wins,false},
 {linkfun,{modfun,riak_kv_wm_link_walker,mapreduce_linkfun}},
 {n_val,3},
 {notfound_ok,true},
 {old_vclock,86400},
 {postcommit,[]},
 {pr,0},
 {precommit,[]},
 {pw,0},
 {r,quorum},
 {rw,quorum},
 {small_vclock,50},
 {w,quorum},
 {young_vclock,20}]

升级后:

[{name,<<"run">>}|undefined]

升级后app_helper:get_env(riak_core, default_bucket_props).返回Undefined。

我发现它会在升级过程中尝试处理 sys.config:

Warning: "_build/prod/rel/cavv/releases/0.1.2/sys.config" missing (optional)

使用生成的 app.conf 是不够的,因为它不包含之前显示的所有配置值。使用它只输出:[{n_val,3}]

可能是 Cuttlefish 无法正确重新加载 conf 文件?

更新2

做更多的挖掘。升级后application:get_all_env(riak_core). 返回不同的值。有什么想法吗?

【问题讨论】:

    标签: erlang rebar3


    【解决方案1】:

    我发现升级后,所有环境值都被清除了:

    http://erlang.org/doc/design_principles/release_handling.html#id84983

    具体来说,应用配置参数是 根据(按优先级递增的顺序)自动更新:

    启动脚本中的数据,从新的应用程序资源中获取 文件 App.app 新的 sys.config 命令行参数 -App Par Val 这意味着在其他系统配置中设置的参数值 文件和使用 application:set_env/3 设置的值被忽略

    要重置 riak_core 设置的值,我使用了一个简单的函数:

    set_defaults() ->
         riak_core_bucket:append_bucket_defaults(riak_core_bucket_type:defaults(default_type)).
    

    我在我的 relup 文件中调用它:

    {apply,{cavv_app,set_defaults,[]}},
    

    默认设置在 riak_core 应用程序启动期间正常设置:

    https://github.com/basho/riak_core/blob/develop/src/riak_core_app.erl#L42

    但是这个函数没有导出也没有暴露。

    不知道这是否是我想出的最优雅的解决方案。欢迎任何想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-12
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多