NWPC业务系统笔记:检查单个时次是否运行完成

目录

数值预报业务系统每天会执行多个循环,例如 GRAPES 全球预报系统每天计算 00、06、12 和 18 共四个时次的预报。 在每天运行的最后,会有一个任务用于清理几天前运行所占用的空间。 整个系统的结构,如下图所示。

GRAPES 全球预报后处理系统的示意图,每天有四个时次,在第二天 02:00 UTC 会执行 housekeep_final 任务清理空间

ecFlow 只有在某个 suite 所有任务都运行完成才会自动滚动到下一天。 如果哪个任务没有正常完成,系统就会卡在这一天,影响后续任务的执行。 最近一段时间,因为任务运行超时被 slurm 杀掉,但任务没有被 aborted,导致任务一直处于 active 状态,容易被值班人员忽略。

目前还没有找到具体的原因。 推测可能是在系统出错时调用 ecflow_client 命令耗时较长,超过被 slurm 杀掉的作业允许的执行时间,导致 ecflow 服务没有接收到 aborted 信号。

当前的系统设计无法处理这种情况。 本文介绍一种检查单个时次是否运行完成的方法,为值班人员提供明确的提示信息。

原理

业务系统在设定 housekeeping 任务启动时间时,假定该时间点当天所有的时次已经完成。 所以,可以设置一组与 housekeeping 同时启动的任务,分别检查各个时次是否完成。 如下图所示:

GRAPES 区域模式系统各个时次的检查任务

实现

ecFlow 提供 complete 触发器,用于在符合条件的情况下跳过某个任务,但 complete 只支持 event 事件,不支持节点。 所以需要在脚本中手动检测任务是否完成。

ecFlow_client 命令无法直接获取某个节点的运行状态。 下面的代码使用 Python API 接口返回指定节点的运行状态字符串。

from __future__ import print_function
import argparse
import os

import ecflow

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", help="ecflow host")
    parser.add_argument("--port", help="ecflow port")
    parser.add_argument("--node-path", help="node path")
    args = parser.parse_args()

    client = ecflow.Client(args.host, args.port)
    client.sync_local()
    defs = client.get_defs()

    node = defs.find_abs_node(args.node_path)
    if node is None:
        print("unknown")
        return

    status = str(node.get_dstate())
    print(status)


if __name__ == "__main__":
    main()

使用下面的命令获取节点状态:

python get_node_status.py \
  --host=login_b01 \
  --port=31071 \
  --node-path=/meso_post/09

如果节点正常结束,命令返回 complete。所以脚本中检查返回值是否为 complete 就可以。

status=$(python ${script_path} \
    --host=${ECF_HOST} --port=${ECF_PORT} \
    --node-path=/meso_post/${HH})

if [ "x${status}" != "xcomplete" ]; then
    echo "============WARNING==============="
    echo "/meso_post/${HH} is not complete!"
    echo "============WARNING==============="
    this_is_an_error
fi