Chinaunix首页 | 论坛 | 博客
  • 博客访问: 484249
  • 博文数量: 28
  • 博客积分: 858
  • 博客等级: 一等列兵
  • 技术积分: 852
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-02 14:13
文章分类

全部博文(28)

文章存档

2020年(1)

2019年(1)

2018年(5)

2017年(1)

2014年(1)

2013年(2)

2012年(17)

分类: LINUX

2012-04-13 10:26:13

    Linux heartbeat是开源的HA软件,很多公司使用heartbeat来做双机,熟悉heartbeat的启动,可以方便我们使用HA的时候帮助我们对启动问题的定位和分析。我们使用的heartbeat版本为3.0,运行系统为Redhat Enterprise 5.3 
    一般我们启用heartbeat,使用service heartbeat start,那下面我们分析使用这条命令/etc/init.d/heartbeat到底做了什么事情:
  1. RunStartStop pre-start 脚本首先执行这个命令,首先监测heartbeat的/etc/ha.d/resource.d目录下是否有startstop脚本,我的机器 ls /etc/ha.d/resource.d/|grep startstop 没有发现这个脚本,所以这步忽略。
  2. 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进程

点击(此处)折叠或打开

  1. do {
  2.                 sleep(1);
  3.                 continue;
  4.             }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)

点击(此处)折叠或打开

  1. id=Gmain_timeout_add_full(PRI_CHECKSIGS, config->heartbeat_ms
  2.     , Gmain_hb_signal_process_pending, NULL, NULL);
注册Gmain_hb_signal_process_pending到主处理进程中。
当收到SIGTERM信号主要在这里处理

点击(此处)折叠或打开

  1. if (handlers&HB_SIG_TERM_SIG) {
  2.             hb_signal_term_action();
  3.         }
主要的处理过程:

点击(此处)折叠或打开

  1. if (curproc->type == PROC_MST_CONTROL) {
  2.         hb_initiate_shutdown(FALSE);
  3.     }else{
  4.         cleanexit(SIGTERM);
  5.     }
master process的话执行hb_initiate_shutdown,其他的话退出。
正常退出过程:

点击(此处)折叠或打开

  1. send_local_status();
  2.     if (!quickshutdown && DoManageResources) {
  3.         /* THIS IS RESOURCE FIXME */
  4.         procinfo->giveup_resources = TRUE;
  5.         hb_giveup_resources();
  6.         /* Do something more drastic in 60 minutes */
  7.         Gmain_timeout_add(1000*60*60, EmergencyShutdown, NULL);
  8.         return;
  9.     }
也就是先发送本机状态给partner,然后give up resouces
最后给子进程发SIGTERM信号
hb_mcp_final_shutdown

点击(此处)折叠或打开

  1. if (!shutdown_last_client_child(SIGTERM)) {
  2.             if (ANYDEBUG) {
  3.                 cl_log(LOG_DEBUG
  4.                 , "hb_mcp_final_shutdown()"
  5.                 "- immediate completion.");
  6.             }
  7.             return hb_mcp_final_shutdown(p); /* phase 1 (no children) */
  8.         }
递归调用直到每个进程退出。
阅读(9684) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~