变更被包含的应用
添加、删除、重启应用的发布处理指令只能作用于主应用。没有针对被包含的应用的相应指令。不过,由于一个被包含的应用其实就是一个有最高督程的监督树,并作为进行包含的应用中的某个督程的子进程被启动的,所以可以手工创建一个 relup 文件。
例如:假设我们有一个发布包含一个应用 prim_app ,它的监督树里有一个督程 prim_sup 。
在发布的新版本中,我们的范例应用 ch_app 要被包含在 prim_app 中。也就是说,它的最高督程要被作为 prim_sup 的子进程来启动。
- 编辑 prim_sup 的代码:
- init(...) ->
- {ok, {...supervisor flags...,
- [...,
- {ch_sup, {ch_sup,start_link,[]},
- permanent,infinity,supervisor,[ch_sup]},
- ...]}}.
- 编辑 prim_app 的 .app 文件:
- {application, prim_app,
- [...,
- {vsn, "2"},
- ...,
- {included_applications, [ch_app]},
- ...
- ]}.
- 创建一个新的 .rel 文件,包含 ch_app :
- {release,
- ...,
- [...,
- {prim_app, "2"},
- {ch_app, "1"}]}.
应用重启
4.a. 一种启动被包含的应用的方式是重启整个 prim_app 应用。一般而言,我们要在 prim_app 的 .appup 文件中使用 restart_application 指令。
但是,如果我们这么做并生成了 relup 文件,它不光会包含重启(即移除再添加) prim_app ,它还会包含启动 ch_app (在降级的情况下是停止)。这是由于 ch_app 也被包含在了新的 .rel 文件中,而旧的里面没有。
所以,正确的 relup 文件要被手工创建,要么重头写要么编辑生成好的版本。启动/停止 ch_app 的指令被替换成了加载/卸载应用的指令:
- {"B",
- [{"A",
- [],
- [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
- {load_object_code,{prim_app,"2",[prim_app,prim_sup]}},
- point_of_no_return,
- {apply,{application,stop,[prim_app]}},
- {remove,{prim_app,brutal_purge,brutal_purge}},
- {remove,{prim_sup,brutal_purge,brutal_purge}},
- {purge,[prim_app,prim_sup]},
- {load,{prim_app,brutal_purge,brutal_purge}},
- {load,{prim_sup,brutal_purge,brutal_purge}},
- {load,{ch_sup,brutal_purge,brutal_purge}},
- {load,{ch3,brutal_purge,brutal_purge}},
- {apply,{application,load,[ch_app]}},
- {apply,{application,start,[prim_app,permanent]}}]}],
- [{"A",
- [],
- [{load_object_code,{prim_app,"1",[prim_app,prim_sup]}},
- point_of_no_return,
- {apply,{application,stop,[prim_app]}},
- {apply,{application,unload,[ch_app]}},
- {remove,{ch_sup,brutal_purge,brutal_purge}},
- {remove,{ch3,brutal_purge,brutal_purge}},
- {purge,[ch_sup,ch3]},
- {remove,{prim_app,brutal_purge,brutal_purge}},
- {remove,{prim_sup,brutal_purge,brutal_purge}},
- {purge,[prim_app,prim_sup]},
- {load,{prim_app,brutal_purge,brutal_purge}},
- {load,{prim_sup,brutal_purge,brutal_purge}},
- {apply,{application,start,[prim_app,permanent]}}]}]
- }.
督程变更
4.b. 另一种方法是通过组合给 prim_sup 添加和删除子进程的指令和加载/卸载所有 ch_app 代码和应用规格的指令,来启动应用(在降级的情况下是停止)。
这次还是要手工创建 relup 文件。你重头写或者编辑生成的版本都可以。首先,在更新 prim_sup 之前,载入 ch_app 的所有代码并加载应用规格。当降级时, prim_sup 应该先被更新,在 ch_app 的代码和应用规格卸载之前。
- {"B",
- [{"A",
- [],
- [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
- {load_object_code,{prim_app,"2",[prim_sup]}},
- point_of_no_return,
- {load,{ch_sup,brutal_purge,brutal_purge}},
- {load,{ch3,brutal_purge,brutal_purge}},
- {apply,{application,load,[ch_app]}},
- {suspend,[prim_sup]},
- {load,{prim_sup,brutal_purge,brutal_purge}},
- {code_change,up,[{prim_sup,[]}]},
- {resume,[prim_sup]},
- {apply,{supervisor,restart_child,[prim_sup,ch_sup]}}]}],
- [{"A",
- [],
- [{load_object_code,{prim_app,"1",[prim_sup]}},
- point_of_no_return,
- {apply,{supervisor,terminate_child,[prim_sup,ch_sup]}},
- {apply,{supervisor,delete_child,[prim_sup,ch_sup]}},
- {suspend,[prim_sup]},
- {load,{prim_sup,brutal_purge,brutal_purge}},
- {code_change,down,[{prim_sup,[]}]},
- {resume,[prim_sup]},
- {remove,{ch_sup,brutal_purge,brutal_purge}},
- {remove,{ch3,brutal_purge,brutal_purge}},
- {purge,[ch_sup,ch3]},
- {apply,{application,unload,[ch_app]}}]}]
- }.