应用程序样例实现一个基本的故障监视器,以监视 DNS 资源 (in.named) 的可靠性。 故障监视器包括:
dns_probe,这是一个使用 nslookup 检验数据服务样例所控制的 DNS 资源是否正在运行的用户定义的程序。 如果 DNS 未运行,此方法将尝试在本地重启该 DNS,或按照重启尝试的次数请求 RGM 将数据服务重定位到其它节点。
dns_monitor_start,这是一个用来启动 dns_probe 的回叫方法。 如果启用了监视操作,则在使数据服务样例联机后,RGM 将自动调用 dns_monitor_start。
dns_monitor_stop,这是一个用来停止 dns_probe 的回叫方法。 使数据服务样例脱机之前,RGM 将自动调用 dns_monitor_stop。
dns_monitor_check,一种调用 Validate 方法的回叫方法,检验配置目录在 PROBE 程序将数据服务故障切换到新节点时是否可用。
dns_probe 程序将实现一个持续运行的进程,用来检验数据服务样例所控制的 DNS 资源是否正在运行。 dns_probe 由 dns_monitor_start 方法启动,使数据服务样例联机后,RGM 将自动调用该方法。 该数据服务由 dns_monitor_stop 方法停止,使数据服务样例脱机前,RGM 将调用该方法。
本小节介绍了应用程序样例中的PROBE 方法的重要方面, 但未介绍所有回叫方法都通用的功能,例如 parse_args() 函数和获取 syslog 工具,这些在为所有方法提供通用功能中介绍。
有关 PROBE 方法的完整列表,请参阅PROBE 程序。
探测程序以死循环的形式运行。 它使用 nslookup 检验适当的 DNS 资源是否正在运行。 如果 DNS 正在运行,探测程序将按照指定的时间间隔(由系统定义的特性 Thorough_probe_interval 进行设置)进行休眠,然后再次进行检查。 如果 DNS 未运行,此程序将尝试在本地重启 DNS,或按照重启尝试的次数请求 RGM 将数据服务重定位到其它节点。
Thorough_probe_interval – 用来设置探测程序休眠的时间段
Probe_timeout — 用来对进行探测操作的 nslookup 命令强制执行探测程序的超时值
Network_resources_used — 用来获取 DNS 服务器的 IP 地址
Retry_count 和 Retry_interval — 用来确定重启尝试的次数和进行计数的时间间隔
Rt_basedir – 用来获取包含 PROBE 程序和 gettime 公用程序的目录
scha_resource_get() 函数可用来获取这些特性的值,并将其存储在 shell 变量中,如下所示。
PROBE_INTERVAL=`scha_resource_get -O THOROUGH_PROBE_INTERVAL \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME` probe_timeout_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \ -G $RESOURCEGROUP_NAME Probe_timeout` PROBE_TIMEOUT=`echo $probe_timeout_info | awk '{print $2}'` DNS_HOST=`scha_resource_get -O NETWORK_RESOURCES_USED -R $RESOURCE_NAME \ -G $RESOURCEGROUP_NAME` RETRY_COUNT=`scha_resource_get -O RETRY_COUNT -R $RESOURCE_NAME -G\ $RESOURCEGROUP_NAME` RETRY_INTERVAL=`scha_resource_get -O RETRY_INTERVAL -R $RESOURCE_NAME -G\ $RESOURCEGROUP_NAME` RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME -G\ $RESOURCEGROUP_NAME`
对于系统定义的特性(例如 Thorough_probe_interval ),scha_resource_get() 仅返回值。 对于扩展特性(例如 Probe_timeout),scha_resource_get() 将返回类型和值。 使用 awk 命令仅能获取值。
探测程序本身是 nslookup 命令的 while 死循环。 在进行 while 循环之前,将设置一个临时文件,以保留 nslookup 应答。 probefail 和 retries 变量初始化为 0。
# Set up a temporary file for the nslookup replies. DNSPROBEFILE=/tmp/.$RESOURCE_NAME.probe probefail=0 retries=0 |
设置探测程序的休眠间隔
使用 hatimerun 启动 nslookup,传送 Probe_timeout 的值并标识目标主机
根据 nslookup 返回代码的成功或失败状态,设置 probefail 变量
如果将 probefail 设置为 1(失败),则可检验对 nslookup 的应答是由数据服务样例发出的还是由其它 DNS 服务器发出的
下面是 while 循环代码。
while : do # The interval at which the probe needs to run is specified in the # property THOROUGH_PROBE_INTERVAL. Therefore, set the probe to sleep # for a duration of THOROUGH_PROBE_INTERVAL. sleep $PROBE_INTERVAL # Run an nslookup command of the IP address on which DNS is serving. hatimerun -t $PROBE_TIMEOUT /usr/sbin/nslookup $DNS_HOST $DNS_HOST \ > $DNSPROBEFILE 2>&1 retcode=$? if [ $retcode -ne 0 ]; then probefail=1 fi # Make sure that the reply to nslookup comes from the HA-DNS # server and not from another nameserver mentioned in the # /etc/resolv.conf file. if [ $probefail -eq 0 ]; then # Get the name of the server that replied to the nslookup query. SERVER=` awk ' $1=="Server:" { print $2 }' \ $DNSPROBEFILE | awk -F. ' { print $1 } ' ` if [ -z "$SERVER" ]; then probefail=1 else if [ $SERVER != $DNS_HOST ]; then probefail=1 fi fi fi |
如果 probefail 变量是 0 (成功)之外的值,这意味着 nslookup 命令超时或表明应答是某个服务器发出的,而不是服务样例的 DNS 发出的。 在每种情况下,DNS 服务器都不能按照预期的情况发挥作用,且故障监视器将调用 decide_restart_or_failover() 函数以确定是在本地重启数据服务,还是请求 RGM 将数据服务重定位到其它节点。 如果 probefail 变量是 0,则会生成一条表明探测程序成功的消息。
if [ $probefail -ne 0 ]; then decide_restart_or_failover else logger -p ${SYSLOG_FACILITY}.err\ -t [$SYSLOG_TAG]\ "${ARGV0} Probe for resource HA-DNS successful" fi |
decide_restart_or_failover() 函数使用时间窗口 (Retry_interval) 和故障计数 (Retry_count) 来确定是在本地重启 DNS,还是请求 RGM 将数据服务重定位到其它节点。 它实现了以下有条件的代码(请参阅PROBE 程序中的 decide_restart_or_failover() 的代码列表)。
如果这是第一次出现故障,重新启动数据服务。 记录一条错误消息并取消 retries 变量中的计数器。
如果不是首次故障,但是时间已经超出了窗口的范围,请重启数据服务。 记录一条错误消息,复位计数器并滑动窗口。
如果时间仍处于窗口的范围内,但已超出重试计数器的计数范围,请故障切换到另一个节点。 如果故障切换未成功,将记录一条错误消息并以状态 1(失败)退出探测程序。
如果时间仍处于窗口的范围内,但是未超出重试计数器的计数范围,请重启数据服务。 记录一条错误消息并取消 retries 变量中的计数器。
如果在指定时间间隔内达到了重启的最大次数,函数将请求 RGM 将数据服务重定位到其它节点。 如果重启的次数在所限制范围之内,或者已超出了时间间隔,以致重新开始计数时,该函数将尝试在同一节点上重启 DNS。 请注意以下关于此函数的信息:
gettime 公用程序用来跟踪两次重启操作之间的时间。 这是驻留在 (Rt_basedir) 目录中的 C 程序。
系统定义的资源特性 Retry_count 和 Retry_interval 可确定重启尝试的次数以及进行计数的时间间隔。 在 RTR 文件中这些特性缺省设置为在 5 分钟(300 秒)时间内尝试 2 次,但是群集管理员可以更改这些值。
系统将调用 restart_service() 函数尝试在同一节点上重启该数据服务。 有关此函数的信息,请参阅下一节重启数据服务。
使用 scha_control() API 函数和 GIVEOVER 选项可以使含有数据服务样例的资源组脱机并在其它节点上重新联机。
decide_restart_or_failover() 调用 restart_service() 函数以试图在同一个节点上重新启动数据服务。 该函数执行以下操作。
它可确定数据服务是否仍然在 PMF 的控制下进行登记。 如果仍然对该服务进行登记,则该函数将:
获取数据服务的 Stop 方法名和 Stop_timeout 值。
使用 hatimerun 启动数据服务的 Stop 方法,并传送 Stop_timeout 值。
(如果成功停止数据服务)获取数据服务的 Start 方法名称和 Start_timeout 值。
使用 hatimerun 启动数据服务的 Start 方法,并传送 Start_timeout 值。
如果该数据服务不再在 PMF 的控制下进行登记,则表明该数据服务已超出了在 PMF 控制下进行重试的最大允许次数,因此可以使用 GIVEOVER 选项调用 scha_control() 函数将数据服务故障切换到其它节点。
function restart_service { # To restart the data service, first verify that the # data service itself is still registered under PMF. pmfadm -q $PMF_TAG if [[ $? -eq 0 ]]; then # Since the TAG for the data service is still registered under # PMF, first stop the data service and start it back up again. # Obtain the Stop method name and the STOP_TIMEOUT value for # this resource. STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM? STOP_METHOD=`scha_resource_get -O STOP \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM? hatimerun -t $STOP_TIMEOUT $RT_BASEDIR/$STOP_METHOD \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \ -T $RESOURCETYPE_NAME if [[ $? -ne 0 ]]; then logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \ “${ARGV0} Stop method failed.” return 1 fi # Obtain the START method name and the START_TIMEOUT value for # this resource. START_TIMEOUT=`scha_resource_get -O START_TIMEOUT \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM? START_METHOD=`scha_resource_get -O START \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM? hatimerun -t $START_TIMEOUT $RT_BASEDIR/$START_METHOD \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \ -T $RESOURCETYPE_NAME if [[ $? -ne 0 ]]; then logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \ “${ARGV0} Start method failed.” return 1 fi else # The absence of the TAG for the dataservice # implies that the data service has already # exceeded the maximum retries allowed under PMF. # Therefore, do not attempt to restart the # data service again, but try to failover # to another node in the cluster. scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \ -R $RESOURCE_NAME fi return 0 } |
如果尝试在本地进行重启的操作以及尝试故障切换到其它节点的操作都失败后,数据服务样例的 PROBE 程序将在失败状态下退出。 它将记录错误消息“故障切换尝试失败”。
在使数据服务样例联机之后,RGM 将调用 Monitor_start 方法来启动 dns_probe 方法。
本小节介绍了应用程序样例中的 Monitor_start 方法的重要方面, 但未介绍所有回叫方法都通用的功能,例如 parse_args() 函数和获取 syslog 工具,这些在为所有方法提供通用功能中介绍。
要获得 Monitor_start 方法的完整列表,请参阅Monitor_start 方法。
此方法使用进程监视工具 (pmfadm) 启动探测程序。
Monitor_start 方法获取 Rt_basedir 特性的值以构造 PROBE 程序的完整路径名。 此方法将使用 pmfadm (-n -1, -t -1) 的无限重试选项启动探测程序,这意味着如果该探测程序无法启动,PMF 将在无限长的时间间隔内尝试无限多次地启动该程序。
# Find where the probe program resides by obtaining the value of the # RT_BASEDIR property of the resource. RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME -G \ $RESOURCEGROUP_NAME` # Start the probe for the data service under PMF. Use the infinite retries # option to start the probe. Pass the resource name, type, and group to the # probe program. pmfadm -c $RESOURCE_NAME.monitor -n -1 -t -1 \ $RT_BASEDIR/dns_probe -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \ -T $RESOURCETYPE_NAME |
使数据服务样例脱机后,RGM 将调用 Monitor_stop 方法停止 dns_probe 的执行。
本小节介绍了应用程序样例中的 Monitor_stop 方法的重要方面, 但未介绍所有回叫方法都通用的功能,例如 parse_args() 函数和获取 syslog 工具,这些在为所有方法提供通用功能中介绍。
要获得 Monitor_stop 方法的完整列表,请参阅Monitor_stop 方法。
此方法将使用进程监视工具 (pmfadm) 查看探测程序是否正在运行,如果正在运行,就停止该程序。
Monitor_stop 方法将使用 pmfadm -q 查看探测程序是否正在运行,如果正在运行,将使用 pmfadm -s 停止该程序。 如果探测程序已停止,该方法仍将成功退出,这可以确保该方法的幂等性。
# See if the monitor is running, and if so, kill it. if pmfadm -q $PMF_TAG; then pmfadm -s $PMF_TAG KILL if [ $? -ne 0 ]; then logger -p ${SYSLOG_FACILITY}.err \ -t [$SYSLOG_TAG] \ "${ARGV0} Could not stop monitor for resource " \ $RESOURCE_NAME exit 1 else # could successfully stop the monitor. Log a message. logger -p ${SYSLOG_FACILITY}.err \ -t [$SYSLOG_TAG] \ "${ARGV0} Monitor for resource " $RESOURCE_NAME \ " successfully stopped" fi fi exit 0 |
请务必通过 pmfadm 使用 KILL 信号停止该探测程序,而不要使用可屏蔽信号,例如 TERM。 否则,Monitor_stop 方法将无限期地挂起,最终将会超时。 导致此问题的原因是必要时 PROBE 方法会调用 scha_control(),以重启或故障切换数据服务。 作为使数据服务脱机进程的一部分,当 scha_control() 调用 Monitor_stop 时,如果 Monitor_stop 使用可屏蔽信号,它将挂起,等待 scha_control() 的完成,且 scha_control() 也将挂起,等待 Monitor_stop 的完成。
如果 Monitor_stop 方法无法停止 PROBE 方法,它将记录一条错误消息。 RGM 将使数据服务样例在主节点上处于 MONITOR_FAILED 状态,此操作可能会影响该主节点。
在探测程序停止之前,Monitor_stop 不应退出。
每当 PROBE 方法视图将包含数据服务的资源组故障切换到新节点上时,RGM 都将调用 Monitor_check 方法。
本小节介绍了应用程序样例中的 Monitor_check 方法的重要方面, 但未介绍所有回叫方法都通用的功能,例如 parse_args() 函数和获取 syslog 工具,这些在为所有方法提供通用功能中介绍。
要获得 Monitor_check 方法的完整列表,请参阅Monitor_check 方法。
必须实现 Monitor_check 方法,以免与当前运行的其它方法发生冲突。
Monitor_check 方法调用 Validate 方法检验 DNS 配置目录在新节点上是否可用。 Confdir 扩展特性指向 DNS 配置目录。 因此,Monitor_check 将获取 Validate 方法的路径和名称以及 Confdir 的值。 它将把此值传送到 Validate,如下所示。
# Obtain the full path for the Validate method from # the RT_BASEDIR property of the resource type. RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME \ -G $RESOURCEGROUP_NAM? # Obtain the name of the Validate method for this resource. VALIDATE_METHOD=`scha_resource_get -O VALIDATE \ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM? # Obtain the value of the Confdir property in order to start the # data service. Use the resource name and the resource group entered to # obtain the Confdir value set at the time of adding the resource. config_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \ -G $RESOURCEGROUP_NAME Confdir` # scha_resource_get returns the type as well as the value for extension # properties. Use awk to get only the value of the extension property. CONFIG_DIR=`echo $config_info | awk `{print $2}'` # Call the validate method so that the dataservice can be failed over # successfully to the new node. $RT_BASEDIR/$VALIDATE_METHOD -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \ -T $RESOURCETYPE_NAME -x Confdir=$CONFIG_DIR |
要了解应用程序样例如何检验一个节点是否适合用作数据服务主机,请参阅Validate 方法。