大数据智能运维实战(八):从调度任务追到计算引擎——补齐排查链路

系列:Spring AI + MCP------大数据智能运维实战

本篇目标:以模拟 Hive 作业为例,从准确的调度运行追到引擎记录;关联缺失或冲突时保留边界。

阅读基础:第七篇的 taskId、runId、attemptId;沿用 lab-07-12 与 Java 17、Spring Boot 4.1.0、Spring AI 2.0.1。

案例说明:全部标识、回执、状态和数据均为虚构;不连接真实 Hive、YARN 或调度平台。

1. 调度页面说 RUNNING,为什么引擎里还在等

"这次日报已经运行半个多小时了,Hive 一定算得很慢。"小周说。

小林指向调度页面:"这个 RUNNING 先说明执行器开始处理了。它是不是已经提交查询,提交以后在排队还是计算,还得往下查。"

小周换到引擎页面,搜出几个名字相近的应用:"选最新那个?"

"先别选。今天同一任务可能运行多次,一次运行还可能重试。名字相近、时间接近,都只能提供线索。"

上一篇解决了"哪一次运行、哪一次尝试"。本篇继续解决:这一次尝试,究竟对应哪条引擎执行记录。

观察时刻仍固定为 2026-09-17 09:40 +08:00 。本篇主样本是 run-current-0917,与上一章已经成功的 run-retry-0917 是两次不同的教学运行。

2. 先画一条能解释来源的关联链

为了便于理解,青禾教学平台设定了这样一条链路:

text 复制代码
任务定义 daily-report
  → 运行 run-current-0917
  → 尝试 a1
  → 模拟 Hive 操作 demo-operation-20
  → 模拟查询 demo-query-20
  → 模拟引擎应用 demo-app-20

这不是把前一个标识改个前缀,就能推算出后一个标识。每一步都来自固定教学数据里的提交回执。

图 1:连线表示有回执支撑的关联,不表示所有 Hive 部署都必须经过同样的执行层次。

HiveServer2 提供客户端执行查询的服务,并支持操作日志;实际执行方式与配置会影响底层执行信息。本文借用这些概念说明如何关联证据,不实现 Hive 客户端。HiveServer2 官方文档

需要特别小心:一个查询不一定对应一个独占、全新的引擎应用。实际环境可能存在会话复用、多个执行阶段或不同执行模式。因此教学返回使用 links 和 applicationIds 列表,没有把"一次查询等于一个应用"写死在契约里。

当没有独立应用时,应该明确返回适用的执行信息或"不适用"。它和"本来应该有关联,但没有采集到"也是两种情况。本文的缺失样本属于后者。

3. 工具先接收运行与尝试,再返回它找到的关联

新增工具叫 ops_trace_engine,参数只有两个:

json 复制代码
{
  "runId": "run-current-0917",
  "attemptId": "a1"
}

工具先验证 a1 确实属于这个运行,再查固定回执。它不接收任意 SQL,不让调用者传入一个文件路径,也不允许模型顺手提供一个"猜到的应用 ID"。

在 InvestigationTools.java 中,入口保持很薄:

java 复制代码
return boundary.execute(context, "ops_trace_engine",
        () -> service.trace(runId, attemptId));

共同边界负责身份、权限、调用额度和超时,服务负责对象与关联语义。这样同一个问题不会在五个工具里写出五套不同的判断。

主样本返回的关联部分如下,省略了外层请求元信息:

json 复制代码
{
  "mappingState": "LINKED",
  "links": [{
    "runId": "run-current-0917",
    "attemptId": "a1",
    "operationId": "demo-operation-20",
    "queryId": "demo-query-20",
    "applicationIds": ["demo-app-20"],
    "source": "SIMULATED_SUBMISSION_RECEIPT",
    "evidenceId": "run-current-0917/receipt-1"
  }]
}

source 说明关联从哪里来,evidenceId 用于在解释中引用。真实接入时,可以映射到允许访问的回执或事件引用,但不要直接暴露内部连接串、任意文件路径或敏感 SQL 文本。

关联本身也需要时间和来源语义。不能拿昨天留下的一条应用记录,补到今天的另一次重试里。本文的整个回执集都属于同一固定教学快照,跨快照校验留给真实数据适配层处理。

4. 关联成功以后,两边状态仍然要分别解释

查询到关联,不代表两个系统的状态就可以合并成一个词。

主样本中:

来源 对象 已有事实
调度运行 run-current-0917 09:00 入队,09:05 启动,观察时仍为 RUNNING
提交回执与日志 尝试 a1 09:06 提交模拟操作,随后记录到查询与应用标识
引擎快照 demo-app-20 09:39 上报 QUEUED
队列快照 demo-batch 09:39 运行数 8,上限 8,原因 QUEUE_RUNNING_LIMIT

这些记录并不矛盾。执行器可以一边保持 RUNNING,一边轮询尚未准入的引擎应用。

教学规则规定队列运行名额上限为 8。这里既有 8/8 的计数,又有引擎给出的 QUEUE_RUNNING_LIMIT 原因,因此可以说:"09:39 的引擎记录表明,这个应用仍在等待队列准入。"

但有两个范围不能越过。

第一,8/8 是教学队列的并发名额,不是集群 CPU 使用率,也不是 YARN 队列容量配置的通用表达式。

第二,09:39 是最近观测时刻。查询时钟是 09:40,不能省略这一分钟的时效差,也不能据此证明从 09:06 到 09:40 一直处于同一状态。

已经拿到了关联链,仍然要保留每一段证据自己的时间。

5. 关联缺失时,不要帮数据"补全剧情"

接着查询 run-unlinked-0917 的 a1。

它有调度运行与尝试记录,却没有可用的引擎提交关联。工具返回:

json 复制代码
{
  "mappingState": "MISSING",
  "links": [],
  "applications": [],
  "nextCheck": "按本次 runId + attemptId 查提交回执"
}

小周问:"那是不是还没提交成功?"

还不能直接下这个结论。缺少回执可能是尚未提交,也可能是回执采集失败、适配没有覆盖该执行路径,或者记录暂时不可用。返回结果只证明当前没有取得可靠关联。

合适的回答是:"能确认执行器已启动,但当前缺少本次尝试到引擎对象的可靠关联,因此无法确认引擎阶段。下一步应核对该次尝试的提交回执和相关日志。"

图 2:缺失时补证据;冲突时先核对候选,不能把列表第一项当成答案。

这个工具返回成功,并不代表"链路完整"。查询可以成功地告诉我们关联缺失,这和数据源超时、请求没有执行成功是不同的情况。第十一篇会把它们放进统一错误处理规则。

6. 找到了两条不同回执,也不能挑一条看起来顺眼的

第三个样本叫 run-conflict-0917。

它给同一次尝试提供了两条互相冲突、尚未确认的关联候选,工具返回 mappingState=AMBIGUOUS,保留候选查询标识和回执引用,但不继续返回某一个候选的应用状态。

这里的"冲突"是样本中明确标记的关联问题。不能反过来说,只要查询关联到多个应用就是冲突。一次查询合法地包含多个执行阶段,与两条互相排斥的回执,是两种不同的情况。

把两种情况区分开,返回结构可以保持简单:

情况 工具怎么做 助手怎么说
有可靠回执 LINKED,保留完整关联列表 按已确认链路继续查
没有可靠关联 MISSING,不补造标识 明确当前无法追到引擎
候选互相冲突 AMBIGUOUS,保留候选与引用 先核对回执,暂停针对单个应用下结论

真正影响诊断质量的,不是"关联率看起来有多高",而是错误关联有没有被悄悄当成确定事实。一条关联错了,后面的指标和日志越丰富,结论反而可能越自信地跑偏。

7. 用三个样本检查链路,而不是只演示成功分支

在已启动的教学服务上,可以通过配套客户端调用:

bash 复制代码
python3 scripts/mcp_client.py ops_trace_engine   '{"runId":"run-current-0917","attemptId":"a1"}'

客户端从环境变量读取教学令牌;完整启动步骤见 lab-07-12/README.md。如果只想自动复现,用 python3 scripts/verify_mcp.py 即可临时启动服务并检查结果。

至少检查以下三组:

runId 预期结果 必须避免的错误
run-current-0917 LINKED,关联到 demo-app-20 把调度 RUNNING 当成引擎正在计算
run-unlinked-0917 MISSING,应用列表为空 用相似任务名猜一个应用
run-conflict-0917 AMBIGUOUS,保留候选 自动选择第一个候选继续诊断

再补一条反例:把 attemptId 改成这次运行中不存在的 a3。工具必须拒绝,不能去别的运行里寻找同名尝试。

对主样本,预期回答可以这样写:

已通过本次尝试的模拟提交回执,将 run-current-0917/a1 关联到 demo-query-20 和 demo-app-20。调度侧保持 RUNNING,但引擎最近一次在 09:39 上报 QUEUED,队列运行数为 8/8,原因是 QUEUE_RUNNING_LIMIT。当前应优先核对队列准入与释放事件;尚不能说明整个等待区间都由同一限制导致。

这依然是预期回答模板,不是某个模型已经通过的验收成绩。

8. 有了准确标识,下一步才值得查日志

小周现在知道,排查链路不是几次模糊搜索,而是一组有来源的关联。

对 run-current-0917/a1,下一步可以查看提交前后发生了什么、轮询有没有异常、队列状态有没有变化。对关联缺失的样本,也可以限定到同一次尝试查提交日志。

下一篇我们就给助手一个受约束的日志查询工具:既能找到异常,也保留前后文;查到一半、采集有缺口或单条消息被截断,都要如实告诉读者。

相关推荐
zhongben123_1 小时前
从0到1开发一款生鲜配送APP:核心技术难点与架构避坑指南
大数据·运维·人工智能·ios·架构·web app
砚底藏山河1 小时前
python量化:实时行情WebSocket断线重连状态机
java·python·websocket·金融
衍生星球1 小时前
【Java 语言】— 方法(方法定义、调用、参数、返回值、方法重载)
java·开发语言·方法
2601_967212721 小时前
可移动轨道插座安全结构、场景适配与安装技术说明
大数据·经验分享·安全
学页官方1 小时前
部署实战】教培系统私有化部署全流程:从云服务器到上线验收
运维·服务器
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 查询评论列表
java·交友
时间售卖铺1 小时前
MySQL 备份
运维·数据库·mysql·云原生
sycmancia2 小时前
Qml——Text元素
java·前端·html
T_Apollo2 小时前
3.1 JVM 工作原理
java