使用 DSDL 的资源类型实现通常都具有一个故障监视器守护程序,该守护程序可执行以下任务。
定期监视所管理的应用程序的运行情况。 监视器守护程序的这一特定方面主要由应用程序决定,各个资源类型之间可能具有较大差别。 DSDL 具有一些内置公用程序函数,用来检查基于 TCP 的简单服务的运行情况。 应用程序实现基于 ASCII 码的协议,例如 HTTP、NNTP、IMAP 和 POP3 都可以通过这些公用程序实现。
使用资源特性 Retry_interval 和 Retry_count 跟踪该应用程序遇到的问题。 当该应用程序完全失败时,确定 PMF 操作脚本是否应重启该服务,或确定是否已迅速积累了较多应用程序失败从而需要考虑进行故障切换。 DSDL 公用程序 scds_fm_action() 和 scds_fm_sleep() 可用来帮助您实现此机制。
采取相应的操作(通常是重启该应用程序或尝试故障切换包含的资源组)。 DSDL 公用程序 scds_fm_action() 可实现这样的算法。 为此它将计算过去 Retry_interval 时间(以秒为单位)内探测失败的当前积累值。
更新资源状态以使应用程序的运行状态可供 scstat 命令和群集管理 GUI 使用。
已对 DSDL 公用程序进行了设计,因此故障监视器守护程序的主循环可以用以下伪代码表示。
对于使用 DSDL 实现的故障监视器,
scds_fm_sleep() 检测到应用程序进程遭到破环的速度相当快,因为通过 PMF 发出的进程破环通知是异步的。 将该情况与频繁唤醒故障监视器以检查服务的运行情况并查找破环的应用程序的情况相比较, 故障检测时间大幅度减少了,从而提高了该服务的可用性。
如果 RGM 拒绝了通过 scha_control(3HA) API 对该服务进行故障切换的尝试操作,则 scds_fm_action() 将重置(遗忘)其当前失败历史记录。 原因在于失败历史记录已超出 Retry_count,如果故障监视器守护程序在下一个重复期内被唤醒并无法成功完成守护程序的运行情况检查,则将再次试图调用 scha_control() ,这可能仍然被拒绝,因为上一个重复期内导致这被拒绝的状态仍然有效。 重置历史记录可以保证故障监视器至少会在下一个重复期内尝试在本地改善该情况(例如,通过应用程序重启的方式)。
在重启失败的情况下,scds_fm_action() 不会重置应用程序失败历史记录,因为如果情况本身没有进行改善,通常会立即尝试使用 scha_control()。
根据失败历史记录的不同,公用程序 scds_fm_action() 会相应地将资源状态更新为 SCHA_RSSTATUS_OK、SCHA_RSSTATUS_DEGRADED 或 SCHA_RSSTATUS_FAULTED。 这样此状态就可用于群集系统管理。
在大多数情况下,应用程序特定运行情况检查操作可以在独立的公用程序(例如 svc_probe())中实现并与此普通主循环相集成。
for (;;) { / * sleep for a duration of thorough_probe_interval between * successive probes. */ (void) scds_fm_sleep(scds_handle, scds_get_rs_thorough_probe_interval(scds_handle)); /* Now probe all ipaddress we use. Loop over * 1. All net resources we use. * 2. All ipaddresses in a given resource. * For each of the ipaddress that is probed, * compute the failure history. */ probe_result = 0; /* Iterate through the all resources to get each * IP address to use for calling svc_probe() */ for (ip = 0; ip < netaddr->num_netaddrs; ip++) { /* Grab the hostname and port on which the * health has to be monitored. */ hostname = netaddr->netaddrs[ip].hostname; port = netaddr->netaddrs[ip].port_proto.port; /* * HA-XFS supports only one port and * hence obtaint the port value from the * first entry in the array of ports. */ ht1 = gethrtime(); /* Latch probe start time */ probe_result = svc_probe(scds_handle, hostname, port, timeout); /* * Update service probe history, * take action if necessary. * Latch probe end time. */ ht2 = gethrtime(); /* Convert to milliseconds */ dt = (ulong_t)((ht2 - ht1) / 1e6); /* * Compute failure history and take * action if needed */ (void) scds_fm_action(scds_handle, probe_result, (long)dt); } /* Each net resource */ } /* Keep probing forever */ |