我使用heart程序在Erlang节点无响应时重新启动。然而,我发现很难理解为什么节点会冻结。SASL日志没有显示任何错误,并且我自己的日志似乎在那些时刻没有显示任何显著的情况。有人可以给出关于调试这种问题的建议吗?
默认情况下,heart程序会发出SIGKILL
信号来杀死无响应的虚拟机,以便可以快速启动新的虚拟机。这使得获取有关虚拟机的任何有用信息几乎不可能。我过去尝试过的方法是修补心脏程序,避免硬性杀死,而是让虚拟机创建崩溃转储和核心转储。我使用了像这样的一个补丁(这个补丁适用于Erlang/OTP R14B02):
--- erts/etc/common/heart.c.orig 2011-04-17 12:11:24.000000000 -0400
+++ erts/etc/common/heart.c 2011-04-17 12:12:36.000000000 -0400
@@ -559,10 +559,11 @@
int res;
if(heart_beat_kill_pid != 0){
pid = (pid_t) heart_beat_kill_pid;
- res = kill(pid,SIGKILL);
+ res = kill(pid,SIGUSR1);
+ sleep(4);
for(i=0; i < 5 && res == 0; ++i){
sleep(1);
- res = kill(pid,SIGKILL);
+ res = kill(pid,i < 2 ? SIGQUIT : SIGKILL);
}
if(errno != ESRCH){
print_error("Unable to kill old process, "
如您所见,使用此补丁后,Heart将首先发出SIGUSR1
信号以尝试让虚拟机创建崩溃转储文件。由于这可能需要一段时间,因此Heart会休眠4秒钟。如果您没有得到完整的崩溃转储文件,则可能需要增加此休眠时间。在此之后,Heart会尝试两次发出SIGQUIT
信号,希望能够获得核心转储文件,如果仍失败,则发出SIGKILL
信号。
请注意,此补丁会降低Heart的虚拟机重启速度,因为需要等待崩溃转储和核心转储文件。如果您在生产环境中使用它,请注意此限制。
http://www.erlang.org/doc/man/dbg.html
简而言之,尝试一下
dbg:tracer(), dbg:p(all,c), dbg:tpl(Module, Function, x).
dbg:ctpl()
请查看文档以获取更多信息。
注意:将模块和函数更改为您要跟踪的内容,将 x 保留不变。您还可以跳过函数,只给出模块和 x。
警告:在实时系统上运行此操作可能会非常危险,因为将打印到 shell 中的信息量可能非常大。
你可以尝试从你的HEART_COMMAND
中调用erlang:halt/1
,从而创建一个无响应节点的崩溃转储。
你可以尝试使用erl_call
工具,例如-a erlang halt 123
。
如果erlang节点无法响应,这也是有趣的信息。
你尝试增加了`HEART_BEAT_TIMEOUT吗?也许节点只是有点拥挤,错过了超时但没有冻结。
dbg
将跟踪信息输出到文件中。可以让程序运行一段时间,只有在检测到故障情况时才检查跟踪信息。 - Adam Lindbergheart
正在重新启动节点 :) 因此显然它没有响应消息。稍后我在日志中看到这些重启,并在重启前一段时间看到其他记录的缺失。 - Alexey Romanov