• 变更被包含的应用
    • 应用重启
    • 督程变更

    变更被包含的应用

    添加、删除、重启应用的发布处理指令只能作用于主应用。没有针对被包含的应用的相应指令。不过,由于一个被包含的应用其实就是一个有最高督程的监督树,并作为进行包含的应用中的某个督程的子进程被启动的,所以可以手工创建一个 relup 文件。

    例如:假设我们有一个发布包含一个应用 prim_app ,它的监督树里有一个督程 prim_sup

    在发布的新版本中,我们的范例应用 ch_app 要被包含在 prim_app 中。也就是说,它的最高督程要被作为 prim_sup 的子进程来启动。

    • 编辑 prim_sup 的代码:
    1. init(...) ->
    2. {ok, {...supervisor flags...,
    3. [...,
    4. {ch_sup, {ch_sup,start_link,[]},
    5. permanent,infinity,supervisor,[ch_sup]},
    6. ...]}}.
    • 编辑 prim_app 的 .app 文件:
    1. {application, prim_app,
    2. [...,
    3. {vsn, "2"},
    4. ...,
    5. {included_applications, [ch_app]},
    6. ...
    7. ]}.
    • 创建一个新的 .rel 文件,包含 ch_app :
    1. {release,
    2. ...,
    3. [...,
    4. {prim_app, "2"},
    5. {ch_app, "1"}]}.

    应用重启

    4.a. 一种启动被包含的应用的方式是重启整个 prim_app 应用。一般而言,我们要在 prim_app.appup 文件中使用 restart_application 指令。

    但是,如果我们这么做并生成了 relup 文件,它不光会包含重启(即移除再添加) prim_app ,它还会包含启动 ch_app (在降级的情况下是停止)。这是由于 ch_app 也被包含在了新的 .rel 文件中,而旧的里面没有。

    所以,正确的 relup 文件要被手工创建,要么重头写要么编辑生成好的版本。启动/停止 ch_app 的指令被替换成了加载/卸载应用的指令:

    1. {"B",
    2. [{"A",
    3. [],
    4. [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    5. {load_object_code,{prim_app,"2",[prim_app,prim_sup]}},
    6. point_of_no_return,
    7. {apply,{application,stop,[prim_app]}},
    8. {remove,{prim_app,brutal_purge,brutal_purge}},
    9. {remove,{prim_sup,brutal_purge,brutal_purge}},
    10. {purge,[prim_app,prim_sup]},
    11. {load,{prim_app,brutal_purge,brutal_purge}},
    12. {load,{prim_sup,brutal_purge,brutal_purge}},
    13. {load,{ch_sup,brutal_purge,brutal_purge}},
    14. {load,{ch3,brutal_purge,brutal_purge}},
    15. {apply,{application,load,[ch_app]}},
    16. {apply,{application,start,[prim_app,permanent]}}]}],
    17. [{"A",
    18. [],
    19. [{load_object_code,{prim_app,"1",[prim_app,prim_sup]}},
    20. point_of_no_return,
    21. {apply,{application,stop,[prim_app]}},
    22. {apply,{application,unload,[ch_app]}},
    23. {remove,{ch_sup,brutal_purge,brutal_purge}},
    24. {remove,{ch3,brutal_purge,brutal_purge}},
    25. {purge,[ch_sup,ch3]},
    26. {remove,{prim_app,brutal_purge,brutal_purge}},
    27. {remove,{prim_sup,brutal_purge,brutal_purge}},
    28. {purge,[prim_app,prim_sup]},
    29. {load,{prim_app,brutal_purge,brutal_purge}},
    30. {load,{prim_sup,brutal_purge,brutal_purge}},
    31. {apply,{application,start,[prim_app,permanent]}}]}]
    32. }.

    督程变更

    4.b. 另一种方法是通过组合给 prim_sup 添加和删除子进程的指令和加载/卸载所有 ch_app 代码和应用规格的指令,来启动应用(在降级的情况下是停止)。

    这次还是要手工创建 relup 文件。你重头写或者编辑生成的版本都可以。首先,在更新 prim_sup 之前,载入 ch_app 的所有代码并加载应用规格。当降级时, prim_sup 应该先被更新,在 ch_app 的代码和应用规格卸载之前。

    1. {"B",
    2. [{"A",
    3. [],
    4. [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    5. {load_object_code,{prim_app,"2",[prim_sup]}},
    6. point_of_no_return,
    7. {load,{ch_sup,brutal_purge,brutal_purge}},
    8. {load,{ch3,brutal_purge,brutal_purge}},
    9. {apply,{application,load,[ch_app]}},
    10. {suspend,[prim_sup]},
    11. {load,{prim_sup,brutal_purge,brutal_purge}},
    12. {code_change,up,[{prim_sup,[]}]},
    13. {resume,[prim_sup]},
    14. {apply,{supervisor,restart_child,[prim_sup,ch_sup]}}]}],
    15. [{"A",
    16. [],
    17. [{load_object_code,{prim_app,"1",[prim_sup]}},
    18. point_of_no_return,
    19. {apply,{supervisor,terminate_child,[prim_sup,ch_sup]}},
    20. {apply,{supervisor,delete_child,[prim_sup,ch_sup]}},
    21. {suspend,[prim_sup]},
    22. {load,{prim_sup,brutal_purge,brutal_purge}},
    23. {code_change,down,[{prim_sup,[]}]},
    24. {resume,[prim_sup]},
    25. {remove,{ch_sup,brutal_purge,brutal_purge}},
    26. {remove,{ch3,brutal_purge,brutal_purge}},
    27. {purge,[ch_sup,ch3]},
    28. {apply,{application,unload,[ch_app]}}]}]
    29. }.