NWPC消息平台:ecFlow 命令消息

目录

本文属于介绍 NWPC 消息平台 系列文章。

NWPC 消息平台中使用的 ecFlow 命令消息 (Ecflow Client Message) 用于记录 ecFlow 命令行程序 ecflow_client 的调用。

ecflow_client 命令

简介

ecflow_client 命令可以实现与 ecFlow 服务的通讯。

ecFlow 实际执行的任务脚本使用 ecflow_client 的子命令 (child command) 实现任务与 ecFlow 服务的通讯。 比如:

  • --init:告知服务任务开始运行
  • --complete:告知服务任务运行完成
  • --aborted:告知服务任务运行结束
  • --event:触发 event
  • --meter:修改 meter 值
  • --label:修改 label 值

上述命令会修改 ecFlow 服务中节点的运行状态或属性。

服务接收到的每条命令都会在 ecFlow 日志文件中记录,从这些记录中可以分析得到节点的状态变化信息。

有关日志条目更详细的介绍请查看以下文章:

背景

既然 ecFlow 日志已保存记录,为什么还要额外记录命令调用?

虽然 ecFlow 会实时生成日志条目,但不意味着日志条目的更新会实时写入到文件中。

笔者曾尝试使用 Flume 和 watchman 等工具实时监视 ecFlow 日志文件,发现并不能实时获取日志更新。 而且在测试时发现,增加对文件的监视可能会对日志文件的更新产生影响,某个 ecFlow 服务的日志在开始监听后长时间不更新。 尚不清楚无法实时监视文件变更的具体原因,不知道是否与操作系统的缓存机制有关,后续也没有进一步进行测试。

所以,目前 NWPC 对 ecFlow 系统的监控都使用 ecFlow Python API 接口获取整个节点树的运行状态。

详情请查看文章《ecflow学习笔记:节点状态监控工具V2》。

但获取的节点树状态仅代表系统在某个时刻的瞬时状态。为了得到节点状态变化信息,需要定时重复获取状态。 保存每次获取的状态信息会带来极大的冗余信息,定时调用 API 接口也会增加 ecFlow 服务的负担。

ecFlow 日志中的 ecflow_client 子命令条目对应 绝大部分 的节点状态变化信息。 因此 NWPC 消息平台模拟日志中的 ecflow_client 子命令条目,设计 ecFlow 命令消息,并增加额外信息,为运维人员提供实时的节点状态变化信息。

命令

ecflow_client 命令使用命令行选项 (option) 调用不同的子命令,命令行选项的值及位置参数作为该子命令的参数。 例如下面的命令更新 meter 值。

ecflow_client --meter=progress 10

其中

  • --meter 是子命令
  • progress 10 是子命令的两个参数,第一个为子命令选项的值,其余均为位置参数

执行命令需要设置 ecFlow 服务地址,可以通过环境变量或命令行参数设置:

  • ECF_HOST--host=<host>:主机名
  • ECF_PORT--port=<host>:端口号

ecflow_client 子命令还必须通过 环境变量 设置额外的参数:

  • ECF_NAME:任务节点路径
  • ECF_PASS:作业密码,由服务端生成
  • ECF_TRYNO:作业执行次数
  • ECF_RID:作业进程标识

ECF_PASS 外,上述参数均是任务运行的重要信息,而 ecFlow 日志仅记录节点路径 ECF_NAME

另外还有一些 NWPC 尚未使用的可选参数:

  • ECF_TIMEOUT:将消息分发给服务端的最大秒数,默认为 24 小时
  • ECF_HOSTFILE:额外的主机名
  • ECF_DENIED:如果服务拒绝连接,提供额外的方式让子命令报错
  • NO_ECF:忽略具体命令,直接返回,用于测试

额外信息

除上述信息外,我们还关注一些保存在环境变量中的额外信息。

比如 ECF_DATE 保存当前任务对应的起报日期。 对于跨天运行的任务,日志记录的时间往往是起报日期的下一天,导致从 ecFlow 日志中很难直接判断任务对应的起报时次。 在某些情况下,单个任务可能会在某一天以不同的 ECF_DATE 多次运行,单纯使用 ecFlow 日志无法区分这种情况。 所以 NWPC 消息平台将 ECF_DATE 作为关键字段记录到 ecFlow 命令消息中。

同时,ecFlow 命令消息也支持记录更多的环境变量。

ecFlow 命令消息

ecFlow 命令消息 (Ecflow Client Message) 用于记录 ecflow_client 命令的调用。

结构

消息结构如下:

globalchartos 系统某FTP上传任务开始运行的消息

其中

  • commandecflow_client 执行的子命令
  • args 是子命令的参数列表
  • envs 是附加的环境变量列表,本例中为空 (null)
  • ecf_ 开头的字段对应 ECF_ 开头的环境变量

示例

ecflow_client --init 命令,通知服务节点开始运行,附带一个参数,与 ECF_RID 值相同

{
  "app" : "nwpc-message-client",
  "type" : "ecflow-client",
  "time" : "2020-10-09T05:05:57.601596751Z",
  "data" : {
    "args" : [
      "13763205"
    ],
    "command" : "init",
    "ecf_date" : "20201009",
    "ecf_host" : "login_b01",
    "ecf_name" : "/globalchartos/00/upload/ftp_deterministic/ftp_base/upload_tograph_base_144",
    "ecf_port" : "31071",
    "ecf_rid" : "13763205",
    "ecf_tryno" : "1",
    "envs" : null
  }
}

ecflow_client --complete 命令,通知服务节点运行完成,没有参数

{
  "app" : "nwpc-message-client",
  "type" : "ecflow-client",
  "time" : "2020-10-09T04:50:24.754182869Z",
  "data" : {
    "args" : null,
    "command" : "complete",
    "ecf_date" : "20201009",
    "ecf_host" : "login_b01",
    "ecf_name" : "/globalchartos/00/deterministic/base/066/wmc_vor_250_sep_066",
    "ecf_port" : "31071",
    "ecf_rid" : "13758984",
    "ecf_tryno" : "1",
    "envs" : null
  }
}

ecflow_client --meter 参数,修改 meter 值,附带两个参数,meter 名称和值

{
  "app" : "nwpc-message-client",
  "type" : "ecflow-client",
  "time" : "2020-10-09T04:46:51.609932174Z",
  "data" : {
    "args" : [
      "progress",
      "10"
    ],
    "command" : "meter",
    "ecf_date" : "20201009",
    "ecf_host" : "login_b01",
    "ecf_name" : "/globalchartos/00/deterministic/base/066/wmc_vor_250_sep_066",
    "ecf_port" : "31071",
    "ecf_rid" : "13758984",
    "ecf_tryno" : "1",
    "envs" : null
  }
}

实现

下面介绍 nwpc-oper/nwpc-message-client 项目中对 ecFlow 命令消息的实现。

与产品事件消息类似,ecFlow 命令消息使用通用事件消息类型 EventMessage

ecFlow 命令消息数据字段 EcflowClientData 定义如下:

type EcflowClientData struct {
    Command    string              `json:"command"`
    Arguments  []string            `json:"args"`
    Envs       []map[string]string `json:"envs"`
    EcflowHost string              `json:"ecf_host"`
    EcflowPort string              `json:"ecf_port"`
    NodeName   string              `json:"ecf_name"`
    NodeRID    string              `json:"ecf_rid"`
    TryNo      string              `json:"ecf_tryno"`
    EcfDate    string              `json:"ecf_date"`
}

参考

nwpc-oper/nwpc-message-client 项目

https://github.com/nwpc-oper/nwpc-message-client

NWPC消息平台 系列文章:

NWPC消息平台:产品事件消息