调试Erlang心跳超时问题

3

我使用heart程序在Erlang节点无响应时重新启动。然而,我发现很难理解为什么节点会冻结。SASL日志没有显示任何错误,并且我自己的日志似乎在那些时刻没有显示任何显著的情况。有人可以给出关于调试这种问题的建议吗?

3个回答

2

默认情况下,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的虚拟机重启速度,因为需要等待崩溃转储和核心转储文件。如果您在生产环境中使用它,请注意此限制。


1
如果您对为什么会冻结有任何想法,可以尝试使用dbg跟踪模块。

http://www.erlang.org/doc/man/dbg.html

简而言之,尝试一下

dbg:tracer(), dbg:p(all,c), dbg:tpl(Module, Function, x).

如果你想停止这个追踪问题
dbg:ctpl()

请查看文档以获取更多信息。

注意:将模块和函数更改为您要跟踪的内容,将 x 保留不变。您还可以跳过函数,只给出模块和 x。

警告:在实时系统上运行此操作可能会非常危险,因为将打印到 shell 中的信息量可能非常大。


1
很遗憾,这样做行不通,因为我无法预测它何时会冻结。 - Alexey Romanov
1
你可以设置 dbg 将跟踪信息输出到文件中。可以让程序运行一段时间,只有在检测到故障情况时才检查跟踪信息。 - Adam Lindberg
另一个可能导致程序挂起的原因是,如果您的代码中有任何接收子句没有包含超时。查找并为它们添加超时子句,并记录错误。 - Sedrik
这是真的,你怎么知道节点挂了呢?你有什么症状? - Sedrik
症状是heart正在重新启动节点 :) 因此显然它没有响应消息。稍后我在日志中看到这些重启,并在重启前一段时间看到其他记录的缺失。 - Alexey Romanov
显示剩余2条评论

1

你可以尝试从你的HEART_COMMAND中调用erlang:halt/1,从而创建一个无响应节点的崩溃转储。

你可以尝试使用erl_call工具,例如-a erlang halt 123

如果erlang节点无法响应,这也是有趣的信息。

你尝试增加了`HEART_BEAT_TIMEOUT吗?也许节点只是有点拥挤,错过了超时但没有冻结。


我这样做了(因为我希望那是这样的),但它似乎实际上会冻结。 - Alexey Romanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接