應用程式範例實作基本故障監視器,以監視 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 是一種回呼方法,當 PROBE 程式將資料服務容錯移轉至新的節點時,該方法會呼叫 Validate 方法以驗證配置目錄是否可用。
dns_probe 程式將實作一個連續執行的程序,來驗證由資料服務範例控制的 DNS 資源是否正在執行。dns_probe 由 dns_monitor_start 方法啟動,當資料服務範例置於離線後,該方法將由 RGM 自動執行。資料服務由 dns_monitor_stop 方法停止,在 RGM 將資料服務範例置於離線前,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_intervalu),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
while 迴圈執行以下作業︰
設定探測的休息間隔
使用 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 秒) 內嘗試兩次,但是管理員可以變更這些值。
將呼叫 restart_service() 函數,以嘗試重新啟動相同節點上的資料服務。請參閱下一小節重新啟動資料服務,以取得有關此函數的資訊。
scha_control() API 函數透過 GIVEOVER 選項將含有資料服務範例的資源群組置於離線,並在其他節點上將其重新置於線上。
restart_service() 函數由 decide_restart_or_failover() 呼叫,用來嘗試在同一節點上重新啟動資料服務。此函數執行以下邏輯︰
決定資料服務是否仍在 PMF 下註冊。如果該服務仍被註冊,此函數將執行以下動作︰
獲取資料服務的 Stop 方法名稱以及 Stop_timeout 值
使用 hatimerun 啟動資料服務的 Stop 方法,同時傳送 Stop_timeout 值
如果資料服務停止成功,則獲取資料服務的 Start 方法名稱以及 Start_timeout 值
使用 hatimerun 啟動資料服務的 Start 方法,同時傳送 Start_timeout 值
如果資料服務不再在 PMF 下註冊,則意味著資料服務已經超出 PMF 允許重試的最大數目。scha_control() 函數由 GIVEOVER 選項呼叫,用來將資料服務容錯移轉至其他節點。
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 程式嘗試在本機上重新啟動失敗,並且嘗試容錯移轉至其他節點也失敗,則它將以失敗狀態結束。該程式記錄訊息 Failover attempt failed。
在資料服務範例被置於線上之後,RGM 將呼叫 Monitor_start 方法來啟動 dns_probe 方法。
本小節說明應用程式範例之 Monitor_start 方法的主要部分。本小節並不說明所有回呼方法的共用功能性,例如 parse_args() 函數。本小節也不說明如何使用 syslog() 函數。為所有方法提供共用功能性說明共用功能性。
如需 Monitor_start 方法的完整清單,請參閱Monitor_start 方法程式碼清單。
此方法使用 PMF (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_start 方法程式碼清單。
該方法使用 PMF (pmfadm) 檢查探測是否正在執行,如果探測正在執行,該方法會將其停止。
Monitor_stop 方法使用 pmfadm -q 查看探測是否正在執行,如果是,則使用 pmfadm -s 來停止探測。如果探測已停止,則該方法無論如何會以成功狀態結束,這樣會保證該方法的等?性。
請確定透過 pmfadm 使用 KILL 訊號來停止探測,而不要使用可以被遮罩的訊號 (如 TERM)。否則,Monitor_stop 方法可能會無限期掛機並最終逾時。原因是當必須重新啟動資料服務或容錯移轉資料服務時,PROBE 方法將呼叫 scha_control()。作為將資料服務置於離線的程序之一部分,scha_control() 呼叫 Monitor_stop 時,如果 Monitor_stop 使用可以被遮罩的訊號,Monitor_stop 會掛機並等待 scha_control() 完成,而 scha_control() 會掛機並等待 Monitor_stop 完成。
# 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
如果 Monitor_stop 方法無法停止 PROBE 方法,則前者會記錄一條錯誤訊息。RGM 在主要節點上將資料服務範例置於 MONITOR_FAILED 狀態,這樣可能導致節點發生錯誤。
Monitor_stop 應該在停止探測之後結束。
每當 PROBE 方法嘗試將含有資料服務的資源群組容錯移轉至新節點時,RGM 均會呼叫 Monitor_check 方法。
本小節說明應用程式範例之 Monitor_check 方法的主要部分。本小節並不說明所有回呼方法的共用功能性,例如 parse_args() 函數。本小節也不說明如何使用 syslog() 函數。為所有方法提供共用功能性說明共用功能性。
如需 Monitor_check 方法的完整清單,請參閱Monitor_start 方法程式碼清單。
必須實作 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 方法如何工作,以瞭解應用程式範例如何驗證節點是否適合於執行資料服務。