erlang作为一种函数式编程语言,得到了越来越多的应用。在学习分布式编程的过程中,在本机使用长名启动报错,信息如下:
{error_logger,{{2014,6,12},{10,56,2}},"Can't set long node name!\nPlease check your configuration\n",[]}
{error_logger,{{2014,6,12},{10,56,2}},crash_report,[[{initial_call,{net_kernel,init,['Argument__1']}},{pid,<0.20.0>},{registered_name,[]},{error_info,{exit,{error,badarg},[{gen_server,init_it,6,[{file,"gen_server.erl"},{line,322}]},{proc_li
b,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}},{ancestors,[net_sup,kernel_sup,<0.10.0>]},{messages,[]},{links,[<0.17.0>]},{dictionary,[{longnames,true}]},{trap_exit,true},{status,running},{heap_size,610},{stack_size,27},{reducti
ons,784}],[]]}
{error_logger,{{2014,6,12},{10,56,2}},supervisor_report,[{supervisor,{local,net_sup}},{errorContext,start_error},{reason,{'EXIT',nodistribution}},{offender,[{pid,undefined},{name,net_kernel},{mfargs,{net_kernel,start_link,[[cat,longnames]]}
},{restart_type,permanent},{shutdown,2000},{child_type,worker}]}]}
{error_logger,{{2014,6,12},{10,56,2}},supervisor_report,[{supervisor,{local,kernel_sup}},{errorContext,start_error},{reason,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}},{offender,[{pid,undefined},{name,net_sup},{mf
args,{erl_distribution,start_link,[]}},{restart_type,permanent},{shutdown,infinity},{child_type,supervisor}]}]}
{error_logger,{{2014,6,12},{10,56,2}},crash_report,[[{initial_call,{application_master,init,['Argument__1','Argument__2','Argument__3','Argument__4']}},{pid,<0.9.0>},{registered_name,[]},{error_info,{exit,{{shutdown,{failed_to_start_child,n
et_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}},[{application_master,init,4,[{file,"application_master.erl"},{line,133}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,23
9}]}]}},{ancestors,[<0.8.0>]},{messages,[{'EXIT',<0.10.0>,normal}]},{links,[<0.8.0>,<0.7.0>]},{dictionary,[]},{trap_exit,true},{status,running},{heap_size,376},{stack_size,27},{reductions,117}],[]]}
{error_logger,{{2014,6,12},{10,56,2}},std_info,[{application,kernel},{exited,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}}},{type,permanent}]}
{"Kernel pid terminated",application_controller,"{application_start_failure,kernel,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}}}"}
Crash dump was written to: erl_crash.dump
Kernel pid terminated (application_controller) ({application_start_failure,kernel,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{k
其中的提示信息 Can't set long node name!\nPlease check your configuration没有明确说是什么原因。结合搜索到的一些信息,和群友提供的答案,结合书本,基本上确定此问题和域名解析有关,情况大致如下:
1.使用-sname时,默认是本地节点,所以,不需要考虑网络交互,也就不存在域名解析问题。
2.使用-name启动时,系统认为需要通过网络交互,那么,在这个时候,不管是局域网还是广域网,都会涉及到域名解析的问题。
使用 erl -name nodename 启动时,默认会使用机器名作域名进行解析请求,此时肯定解析是无法成功的,所以报错。知道了问题原因,那么解决起来就会有途径可以遵循了。
解决方法有多个,分别如下:
(1)使用erl -name [email protected]启动,
这种方法,借用了127.0.0.1是指向本机的约定来解决此问题的。因为已经提供了具体的ip指向,所以这个时候,不再需要解析了。所以会成功。这个方法是erlang群的群友提供的,在此表示感谢。
(2)和方法1类似,但是用本机的真实ip来处理:erl -name nodename@本机ip地址。
该方法和方法一的原理是一样的,当然,这个地址是真实的,不是模拟的,这个很重要。所以就逻辑性而言,这个方法要更好一些。
(3) 直接使用机器名:erl -name nodename@hostname
由于在这里直接指明了机器名,也就是本机的机器名,所以在这里也不存在解析问题了。问题得到了解决。在这里有个问题:也就是完整长名时的处理流程和只有nodename的长名时的区别在哪里?这个貌似只有看源代码才能回答
(4)使用host文件解析:这个方法是最好的方法,是适合用在部署环境中,因为此时,机器名也并无必要通过dns系统解析。
ok,问题解决了。那么问题是在最常规的-name nodename 时,erlang使用什么来请求dns但是没有结果呢? 在我的出问题环境中,机器名是 hostname,但是 host文件中只有localhost的配置。所以,此时应当是使用了机器名,去请求dns解析,没有解析成功而导致的。而在使用nodename@hostname时,应该在发现hostname是本机后,就没有再去解析了。