博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【原创】Erlang 之 heart 功能
阅读量:5942 次
发布时间:2019-06-19

本文共 16628 字,大约阅读时间需要 55 分钟。

hot3.png

在霸爷博文《
》中写到
-=-=-=-=- 我是88界奥斯卡颁奖礼的分隔线 -=-=-=-=-
      我们写的程序不可能都没有 bug ,都存在 crash 的危险。很多时候我们需要个看门狗(watchdog)程序,在发现系统不正常的时候,就把系统重新启动。这类 watchdog 程序从内核到各种高可用程序都会设置有一个。erlang 系统当然不能免俗,也有个 heart 。
我们来看下流程和效果:
$ export HEART_COMMAND="erl -heart"$ erl -heartheart_beat_kill_pid = 12640Erlang R15B03 (erts-5.9.3.1) 1 [64-bit] [smp:16:16] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.9.3.1  (abort with ^G)1> os:getpid()."12640"2>CTRL + Z 挂起 erlang$ pstree -p…+-beam.smp(12640)-+-heart(12670)| | | |-{beam.smp}(12647)| | | |-{beam.smp}(12648)| | | |-{beam.smp}(12650)| | | |-{beam.smp}(12653)| | | |-{beam.smp}(12654)| | | |-{beam.smp}(12655)| | | |-{beam.smp}(12656)| | | |-{beam.smp}(12657)| | | |-{beam.smp}(12658)| | | |-{beam.smp}(12659)| | | |-{beam.smp}(12660)| | | |-{beam.smp}(12661)| | | |-{beam.smp}(12662)| | | |-{beam.smp}(12663)| | | |-{beam.smp}(12664)| | | |-{beam.smp}(12665)| | | |-{beam.smp}(12666)| | | |-{beam.smp}(12667)| | | |-{beam.smp}(12668)| | | `-{beam.smp}(12669)| | `-pstree(13702)…$ heart: Fri Aug 23 20:36:25 2013: heart-beat time-out, no activity for 65 secondsheart_beat_kill_pid = 27920
      我们看到 erl 重新被启动起来了。现在简单的分析下原理。
heart 由两部份组成
  1. 外部程序: heart
  2. erlang port 模块: heart.erl
      当开启 heart 的时候(erl –heart xxx) 外部程序 heart 被 erlang 模块 heart.erl 作为独立的(子)进程启动起来,监视 emulator 的运作。heart.erl 每隔一定的时间向 heart 外部程序报告状态。当外部 heart 没有监测到心跳的时候就要采取行动,重新运行 $HEART_COMMAND 所指定的命令。
heart 机制有两个用处
  1. erlang 虽然内置了很多 supervisor,可以保证 process 的高可靠性,但是假如 emulator 死亡了,那这一切都消失了,erlang 只能靠 heart 来重新启动。
  2. 热部署的时候 release_handling 需要重新启动 emulator 的时候也必须借助外部程序,即 heart 来辅助。
所以在 heart 模式下,你的 erlang 程序是杀不掉的,除非你先 kill 掉 heart 进程,这个 pid 就是启动的时候输出的 heart_beat_kill_pid (从下面我的实验中可以看出,霸爷的这个结论是错误的!)。
祝玩得开心!
-=-=-=-=- 我是88界奥斯卡颁奖礼的分隔线 -=-=-=-=-
基于上述内容,
实验验证如下
【验证博文中的操作】
[root@Betty coredump_test]# export HEART_COMMAND="erl -heart"     -- 执行 heart 重启业务时执行的命令[root@Betty coredump_test]# erl -heart                            -- 启动 heart 功能heart_beat_kill_pid = 4904Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]Eshell V6.0  (abort with ^G)1> 1> os:getpid()."4904"2> [1]+  Stopped                 erl -heart              -- 这里通过 Ctrl + Z 挂起[root@Betty coredump_test]# [root@Betty coredump_test]# [root@Betty coredump_test]# heart: Mon Mar  7 15:09:49 2016: heart-beat time-out, no activity for 65 seconds   -- 65 秒后输出该打印信息heart_beat_kill_pid = 5066[1]+  已杀死               erl -heart[root@Betty coredump_test]#
另一个窗口
[root@Betty ~]# ps ajxf PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND ... 1890  3925  3925  3925 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1  3925  3927  3927  3927 pts/1     4904 Ss       0   0:00      \_ -bash 3927  4904  4904  3927 pts/1     4904 Sl+      0   0:00          \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /us 4904  4926  4926  4926 ?           -1 Ss       0   0:00              \_ heart -pid 4904...[root@Betty ~]# pstree -pinit(1)─┬─abrtd(2369)        ...        ├─sshd(1890)─┬─sshd(3465)─┬─bash(4576)        │            │            └─bash(14788)───pstree(5058)        │            └─sshd(3925)───bash(3927)───beam.smp(4904)─┬─heart(4926)        │                                                       ├─{beam.smp}(4908)        │                                                       ├─{beam.smp}(4909)        │                                                       ├─{beam.smp}(4910)        │                                                       ├─{beam.smp}(4911)        │                                                       ├─{beam.smp}(4912)        │                                                       ├─{beam.smp}(4913)        │                                                       ├─{beam.smp}(4914)        │                                                       ├─{beam.smp}(4915)        │                                                       ├─{beam.smp}(4916)        │                                                       ├─{beam.smp}(4917)        │                                                       ├─{beam.smp}(4918)        │                                                       ├─{beam.smp}(4919)        │                                                       ├─{beam.smp}(4920)        │                                                       ├─{beam.smp}(4921)        │                                                       ├─{beam.smp}(4922)        │                                                       ├─{beam.smp}(4923)        │                                                       ├─{beam.smp}(4924)        │                                                       └─{beam.smp}(4925)        ...[root@Betty ~]# ps ajxf|grep heart14788  5061  5060 14788 pts/3     5060 S+       0   0:00  |   |   \_ grep heart 3927  4904  4904  3927 pts/1     3927 Tl       0   0:00          \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 4904  4926  4926  4926 ?           -1 Ss       0   0:00              \_ heart -pid 4904[root@Betty ~]# [root@Betty ~]# ps ajxf|grep heart         -- 65 秒后输出内容发生了变化14788  5096  5095 14788 pts/3     5095 S+       0   0:00  |   |   \_ grep heart    1  4926  4926  4926 ?           -1 Ss       0   0:00 heart -pid 4904 4926  5066  4926  4926 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5066  5088  5088  5088 ?           -1 Ss       0   0:00      \_ heart -pid 5066[root@Betty ~]#
【验证手动杀死各类进程的效果】
后台启动 erlang 进程
[root@Betty ~]# erl -heart -detached
可以看到,此时创建了两个进程:erlang 业务进程 + heart 子进程
[root@Betty ~]# ps ajxf|grep heart|grep -v grep    1  5505  5504  5504 ?           -1 Sl       0   0:00 /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart -noshell -noinput 5505  5524  5524  5524 ?           -1 Ss       0   0:00  \_ heart -pid 5505[root@Betty ~]#
杀死 erlang 业务进程后,能看到其 heart 子进程会重新创建 erlang 业务进程和新 heart 子进程。
[root@Betty ~]# kill -9 5505[root@Betty ~]# ps ajxf|grep heart|grep -v grep    1  5524  5524  5524 ?           -1 Ss       0   0:00 heart -pid 5505 5524  5534  5524  5524 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5534  5556  5556  5556 ?           -1 Ss       0   0:00      \_ heart -pid 5534[root@Betty ~]#
再一次杀死 erlang 业务进程,可以看到 erlang 进程的父 heart 进程也消失了,而 erlang 进程的 heart 子进程会重新启动 erlang 业务进程和其 heart 子进程。
[root@Betty ~]# kill -9 5534[root@Betty ~]# [root@Betty ~]# ps ajxf|grep heart|grep -v grep    1  5556  5556  5556 ?           -1 Ss       0   0:00 heart -pid 5534 5556  5568  5556  5556 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5568  5590  5590  5590 ?           -1 Ss       0   0:00      \_ heart -pid 5568[root@Betty ~]#
杀死 erlang 业务进程的父 heart 进程,可以看到对 erlang 业务进程和其子 heart 进程无任何影响。
[root@Betty ~]# [root@Betty ~]# kill -9 5556[root@Betty ~]# ps ajxf|grep heart|grep -v grep    1  5568  5556  5556 ?           -1 Sl       0   0:00 /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5568  5590  5590  5590 ?           -1 Ss       0   0:00  \_ heart -pid 5568[root@Betty ~]#
再一次杀死 erlang 业务进程,能看到其 heart 子进程会重新创建 erlang 业务进程和新 heart 子进程。
[root@Betty ~]# [root@Betty ~]# kill -9 5568[root@Betty ~]# ps ajxf|grep heart|grep -v grep    1  5590  5590  5590 ?           -1 Ss       0   0:00 heart -pid 5568 5590  5605  5590  5590 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5605  5627  5627  5627 ?           -1 Ss       0   0:00      \_ heart -pid 5605[root@Betty ~]#
杀死 erlang 业务进程的 heart 子进程,可以看到 erlang 业务进程也随之消失了。
[root@Betty ~]# [root@Betty ~]# kill -9 5627[root@Betty ~]# ps ajxf|grep heart|grep -v grep[root@Betty ~]#
【验证通过不同信号杀死进程的效果】
以下内容均在窗口 1 中观察
初次启动[root@Betty ~]# erl -heartheart_beat_kill_pid = 5668Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]Eshell V6.0  (abort with ^G)1> (此时在窗口 2 中 kill -9 xxx)1>1> 已杀死heart: Mon Mar  7 15:48:42 2016: Erlang has closed.heart_beat_kill_pid = 5697[root@Betty ~]# (此时在窗口 2 中再次 kill -9 xxx )此时能看到如下一行信息输出,这是由创建 erlang 业务进程的 heart 父进程输出的,下同。[root@Betty ~]# heart: Mon Mar  7 15:49:05 2016: Executed "erl -heart" -> 9. Terminating.heart: Mon Mar  7 15:49:05 2016: Erlang has closed.heart_beat_kill_pid = 5725[root@Betty ~]# [root@Betty ~]# [root@Betty ~]# heart: Mon Mar  7 15:49:23 2016: Executed "erl -heart" -> 9. Terminating.heart: Mon Mar  7 15:49:23 2016: Erlang has closed.heart_beat_kill_pid = 5754[root@Betty ~]# (此时在窗口 2 中 kill -15 xxx )[root@Betty ~]# heart: Mon Mar  7 15:49:56 2016: Executed "erl -heart" -> 15. Terminating.heart: Mon Mar  7 15:49:56 2016: Erlang has closed.heart_beat_kill_pid = 5783[root@Betty ~]# (此时在窗口 2 中 kill -SIGUSR1 xxx )此时能看到,有生成 crash dump 文件的信息,并最后通过 -9 信号杀死 erlang 业务进程(没有找到生成的 crash dump 文件)。[root@Betty ~]# heart: Mon Mar  7 15:50:42 2016: Erlang is crashing .. (waiting for crash dump file)heart: Mon Mar  7 15:50:42 2016: Executed "erl -heart" -> 9. Terminating.heart_beat_kill_pid = 5816[root@Betty ~]# 再来一次,仍旧没找到 crash dump 文件[root@Betty ~]# [root@Betty ~]# heart: Mon Mar  7 15:52:58 2016: Erlang is crashing .. (waiting for crash dump file)heart: Mon Mar  7 15:52:58 2016: Executed "erl -heart" -> 9. Terminating.heart_beat_kill_pid = 5851[root@Betty ~]# (此时在窗口 2 中 kill -SIGUSR2 xxx )[root@Betty ~]# heart: Mon Mar  7 15:54:17 2016: Executed "erl -heart" -> 12. Terminating.heart: Mon Mar  7 15:54:17 2016: Erlang has closed.heart_beat_kill_pid = 5884[root@Betty ~]# (此时在窗口 2 中 kill -SIGSEGV xxx )可以看到,此时在当前目录生成了操作系统的 core 文件。[root@Betty ~]# heart: Mon Mar  7 15:55:26 2016: Executed "erl -heart" -> 139. Terminating.heart: Mon Mar  7 15:55:26 2016: Erlang has closed.heart_beat_kill_pid = 5915[root@Betty ~]# [root@Betty ~]# ll总用量 11132...-rw-------   1 root root 107769856 3月   7 15:55 core.5884...[root@Betty ~]#(此时在窗口 2 中 kill -SIGABRT xxx )可以看到,此时在当前目录同样生成了操作系统的 core 文件。[root@Betty ~]# heart: Mon Mar  7 15:56:59 2016: Executed "erl -heart" -> 134. Terminating.heart: Mon Mar  7 15:56:59 2016: Erlang has closed.heart_beat_kill_pid = 5949[root@Betty ~]# [root@Betty ~]# ll总用量 21880...-rw-------   1 root root 107769856 3月   7 15:55 core.5884-rw-------   1 root root 107769856 3月   7 15:56 core.5915...[root@Betty ~]# (此时在窗口 2 中 killall heart)此时可以看到生成了 erl_crash.dump 文件[root@Betty ~]# Crash dump was written to: erl_crash.dumpKernel pid terminated (heart) ()[root@Betty ~]# [root@Betty ~]# ll总用量 780..-rw-r-----   1 root root 396922 3月   7 16:10 erl_crash.dump...
以下内容均在窗口 2 中观察
[root@Betty upu]# ps ajxf|grep heart|grep -v grep 3927  5668  5668  3927 pts/1     5668 Sl+      0   0:00          \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5668  5690  5690  5690 ?           -1 Ss       0   0:00              \_ heart -pid 5668[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -l 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR111) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+338) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+843) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-758) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-263) SIGRTMAX-1  64) SIGRTMAX[root@Betty upu]# [root@Betty upu]# kill -9 5668[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5690  5690  5690 ?           -1 Ss       0   0:00 heart -pid 5668 5690  5697  5690  5690 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5697  5719  5719  5719 ?           -1 Ss       0   0:00      \_ heart -pid 5697[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -9 5697[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5719  5719  5719 ?           -1 Ss       0   0:00 heart -pid 5697 5719  5725  5719  5719 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5725  5747  5747  5747 ?           -1 Ss       0   0:00      \_ heart -pid 5725[root@Betty upu]# [root@Betty upu]# kill -9 5725[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5747  5747  5747 ?           -1 Ss       0   0:00 heart -pid 5725 5747  5754  5747  5747 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5754  5776  5776  5776 ?           -1 Ss       0   0:00      \_ heart -pid 5754[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -15 5754[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5776  5776  5776 ?           -1 Ss       0   0:00 heart -pid 5754 5776  5783  5776  5776 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5783  5805  5805  5805 ?           -1 Ss       0   0:00      \_ heart -pid 5783[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -SIGUSR1 5783[root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5805  5805  5805 ?           -1 Ss       0   0:00 heart -pid 5783 5805  5816  5805  5805 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5816  5838  5838  5838 ?           -1 Ss       0   0:00      \_ heart -pid 5816[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -SIGUSR1 5816[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5838  5838  5838 ?           -1 Ss       0   0:00 heart -pid 5816 5838  5851  5838  5838 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5851  5873  5873  5873 ?           -1 Ss       0   0:00      \_ heart -pid 5851[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -SIGUSR2 5851[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5873  5873  5873 ?           -1 Ss       0   0:00 heart -pid 5851 5873  5884  5873  5873 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5884  5906  5906  5906 ?           -1 Ss       0   0:00      \_ heart -pid 5884[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -SIGSEGV 5884[root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5906  5906  5906 ?           -1 Ss       0   0:00 heart -pid 5884 5906  5915  5906  5906 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5915  5938  5938  5938 ?           -1 Ss       0   0:00      \_ heart -pid 5915[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# kill -SIGABRT 5915[root@Betty upu]# [root@Betty upu]# ps ajxf|grep heart|grep -v grep    1  5938  5938  5938 ?           -1 Ss       0   0:00 heart -pid 5915 5938  5949  5938  5938 ?           -1 Sl       0   0:00  \_ /usr/local/lib/erlang/erts-6.0/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -heart 5949  5971  5971  5971 ?           -1 Ss       0   0:00      \_ heart -pid 5949[root@Betty upu]# [root@Betty upu]# [root@Betty upu]# killall heart

补充:
      很久之前写过一篇文章,《》,其中的 keepalive 功能和本文中 erlang 的 heart 功能类似,差别在于 erlang 中的实现为,业务作为父进程,heart 作为子进程;而我之前那篇文章中的实现是倒过来的~~

转载于:https://my.oschina.net/moooofly/blog/632784

你可能感兴趣的文章
MP4视频播放器代码
查看>>
Nginx 匹配 iphone Android 微信
查看>>
ldap
查看>>
Yum软件仓库配置
查看>>
linux 压缩与解压总结
查看>>
mysql脚本1064 - You have an error in your SQL syntax; check the manual
查看>>
nessus 本地扫描(一)
查看>>
linux服务器磁盘陈列
查看>>
python----tcp/ip http
查看>>
我的友情链接
查看>>
第一本docker书学习笔记1-3章
查看>>
一個典型僵尸網絡淺析
查看>>
vmware克隆Centos6.4虚拟机网卡无法启动问题
查看>>
dba学习
查看>>
asterisk配置
查看>>
GA操作步骤和技巧(二)——用户行为分析
查看>>
shell中while循环里使用ssh的注意事项
查看>>
SHELL获取计算机外网ip的几种写法
查看>>
博客正在搬迁中
查看>>
触发器与存储过程的区别
查看>>