heartbeat 启动和关闭过程分析

发布时间:2020-04-11编辑:脚本学堂
heartbeat是开源的HA软件,很多公司使用heartbeat来做双机,熟悉heartbeat的启动,可以方便我们使用HA的时候帮助我们对启动问题的定位和分析。
我们使用的heartbeat版本为

heartbeat是开源的HA软件,很多公司使用heartbeat来做双机,熟悉heartbeat的启动,可以方便我们使用HA的时候帮助我们对启动问题的定位和分析。
我们使用的heartbeat版本为3.0,运行系统为redhat Enterprise 5.3。
一般我们启用heartbeat,使用service heartbeat start,那下面我们分析使用这条命令/etc/init.d/heartbeat到底做了什么事情:

RunStartStop pre-start 脚本首先执行这个命令,首先监测heartbeat的/etc/ha.d/resource.d目录下是否有startstop脚本,我的机器 ls /etc/ha.d/resource.d/|grep startstop 没有发现这个脚本,所以这步忽略。

StartHA 启动HA,这里首先检查是否启用CRM模块,我这里没有启用,然后检查/etc/ha.d/haresources的合法性,然后初始化watchdog模块,这个需要根据ha.cf配置来选择是否加载生成wachdog,然后创建/var/run下面需要的目录,包括heartbeat和crm目录,heartbeat又有ccm crm dopd目录。下面检查haresouces是否存在,具体逻辑是如果/etc/ha.d/ipresouces存在并且haresouces不存在,重命名ipresouces为haresouces,然后StartSBD 这个主要是启动/sbin/sbd,我这里不存在这个东西,所以没有启动,具体sbd做什么我也不知道,暂时不考虑细节。最后是start_heartbeat,实际上是执行/usr/lib/heartbeat/heartbeat >& /dev/null,至此我们找到具体启动heartbeat程序的入口点了。

我们从heartbeat的源代码入手,一步步揭开heartbeat启动的神秘面纱,首先我们找heartbeat.c的main函数,我们关注几个命令行参数d的话是开启debug模式,这个对我们调试非常有用,也就是说我们在启动脚本里启动的时候加上-d,heartbeat开启debug模式,将提供给我们非常多的信息。-k是在关闭heartbeat选项,如果实际上heartbeat脚本里关闭heartbeat就是传递-k给heartbeat应用。启动的主要是在StartHeartbeat:中的initialize_heartbeat,这个初始化heartbeat的主要几个进程。
initialize_heartbeat:初始化heartbeat
SetupFifoChild:建立fifo进程
make_io_childpair:建立read 和 write进程
master_control_process:建立master进程
至此heartbeat启动完毕。

下面我们看一下heartbeat如何关闭的,当我们传递-k参数给程序的时候,其实程序主要发信号SIGTERM给master进程
 

复制代码 代码如下:
do {
      sleep(1);
      continue;
}while (CL_KILL((pid_t)running_hb_pid, 0) >= 0);

running_hb_pid是pid file记录的heartbeat的进程ID 也就是master进程的pid,也就是说每隔一秒给master进程发送SIGTERM信号,直到master进程宕掉,才会退出。
那我们就可以看master进程对SIGTERM信号的处理,
hb_signal_set_master_control_process(NULL)
 

复制代码 代码如下:
id=Gmain_timeout_add_full(PRI_CHECKSIGS, config->heartbeat_ms
        , Gmain_hb_signal_process_pending, NULL, NULL);

注册Gmain_hb_signal_process_pending到主处理进程中。
当收到SIGTERM信号主要在这里处理
 

复制代码 代码如下:
if (handlers&HB_SIG_TERM_SIG) {
    hb_signal_term_action();
}

主要的处理过程:
 

复制代码 代码如下:
if (curproc->type == PROC_MST_CONTROL) {
      hb_initiate_shutdown(FALSE);
  }else{
  cleanexit(SIGTERM);
}

master process的话执行hb_initiate_shutdown,其他的话退出。
正常退出过程:
 

复制代码 代码如下:
send_local_status();
        if (!quickshutdown && DoManageResources) {
            /* THIS IS RESOURCE FIXME */
            procinfo->giveup_resources = TRUE;
            hb_giveup_resources();
            /* Do something more drastic in 60 minutes */
            Gmain_timeout_add(1000*60*60, EmergencyShutdown, NULL);
            return;
        }

也就是先发送本机状态给partner,然后give up resouces
最后给子进程发SIGTERM信号
hb_mcp_final_shutdown
 

复制代码 代码如下:
if (!shutdown_last_client_child(SIGTERM)) {
                if (ANYDEBUG) {
                    cl_log(LOG_DEBUG
                    , "hb_mcp_final_shutdown()"
                    "- immediate completion.");
                }
                return hb_mcp_final_shutdown(p); /* phase 1 (no children) */
            }

递归调用直到每个进程退出。