在分布式系统中,因为涉及到大量的机器,所以部署略微有些繁琐。
使用Erlang开发的系统,我们可以通过boot_server来加载我们的代码,免去了ssh登陆服务器,更新代码这样繁琐的步骤。我们只需要将最新的beam文件放到一个server,作为Erlang的boot_server,其他的机器启动Erlang时,通过连接这个Boot Server加载最新的应用代码,完成程序的启动。
架设Server ip为:8.17.85.135
其中一个Client为: 124.118.219.104
启动一个Boot Server涉及的主要模块为erl_boot_server,我们可以通过erlang_boot_server:start/1启动boot server,通过erl_boot_server:add_slave/1加载一个slave,也就是允许连接本机从而加载代码的client。我们也可以通过kernel config来启动boot server,这样更简单:
bserver.config:
[
{kernel, [{start_boot_server, true} ,
{boot_server_slaves, [{124,118,219,104}]}]}
].
(注:根据Erlang 文档,slave可以采用atom, string, tuple多种方式来表示,可是我尝试只能使用tuple,不知是否bug?)
随后启动
erl -setcookie "cookie" -config bserver
至此,我们的boot server就启动成功了,接下来让我们的client从boot server启动。
client:
erl -loader inet -hosts "8.17.85.135" -id node1 -setcookie "cookie"
很遗憾,在我的机器,没有启动成功,因为我client是widnows xp系统。
boot server启动对client的要求
1. Slave在Boot Server的Slaves列表中
2. Erlang OTP版本相同
3. Cookie设置相同
4. 路径一致
以上4点不一定准确,需要我回头在家中的linux上进行尝试,呵呵,本人保留对以上4点要求修改的的权力 :)
根据文档循规蹈矩的走了一遍,有很多疑问和不解,需要去代码中遨游一翻了。
根据init.erl, kernel.erl, erl_prim_loader.erl我简单的罗列了下面的启动过程:
erl启动过程:
1. shell中输入 erl ......
2. emulator调用init:boot/1启动(通过 erlang:whereis(init)返回pid为<0,0,0>,init是第一个process)
3. 启动erl_prim_loader,其负责获取具体的文件从本地(efile)或远程的boot_server(inet)
4. 根据-boot选项,获取boot script文件名称,通过erl_prim_loader获取boot脚本
5. 解析boot script,调用init:eval_script/8执行对应的语句
6. boot script执行完成后,调用init:start_em/1启动erl参数中-s -run对应的模块
7. 执行完毕,启动完成
对于Erlang系统的启动是根据boot script,通过erl_prim_loader从local或server获取具体的module BinCode
随后通过erlang:load_module加载。
有个问题,这里的erl_prim_loader,要么是通过efile,要么是通过inet,有没有一个hybrid的版本呢,我可以让部分 module通过inet加载,而部分通过local加载,通过修改boot.script可以么?这个需要寻找一个好的方案,期待答案....