新闻详情

新闻详情

首页 / 资讯中心 / 详情

SeaTunnel 的 Zeta 引擎采用集群模式运行作业。

发布时间:2026/11/4 18:23:48来源:尧图网络
SeaTunnel 的 Zeta 引擎采用集群模式运行作业。
其中Master 节点负责管理作业级状态Worker 节点负责执行 Task Group。当用户发起 Cancel 操作时Master 需要向对应的 Worker 发送取消请求。任务结束或取消完成后Worker 再将最终状态回传给 Master。简化后的流程如下用户发起 Cancel ↓ Master 向 Worker 发送取消请求 ↓ Worker 取消或完成任务 ↓ Worker 向 Master 汇报最终状态 ↓ Master 更新 Job 状态乍看之下这个流程并不复杂。但在分布式系统中每一个环节都可能受到节点故障、集群成员变化以及 Master 恢复过程等因素的影响。而这些因素都可能引发竞态条件Race Condition。问题现象问题的表现很直接Job 一直停留在 CANCELING 状态用户已经执行了取消操作但任务始终无法进CANCELED等最终状态。最开始我把排查重点放在Master → Worker这条取消请求链路上。第一个怀疑对象取消请求链路在 Master 端SeaTunnel 会向 Worker 发送CancelTaskOperation。这里有一个关键逻辑在发送取消请求之前系统会先检查当前任务所在的执行节点是否仍然存在于集群成员列表中。核心逻辑如下while (!taskFuture.isDone() nodeEngine .getClusterService() .getMember(executionAddress getCurrentExecutionAddress()) ! null) { try { nodeEngine .getOperationService() .createInvocationBuilder( Constant.SEATUNNEL_SERVICE_NAME, new CancelTaskOperation(taskGroupLocation), executionAddress) .invoke() .get(); return; } catch (Exception e) { Thread.sleep(2000); } }这一点立刻引起了我的注意。如果由于心跳异常等原因Worker 节点暂时从集群视图中消失那么循环可能会直接退出甚至连 Cancel 请求都没有发送出去。因此我最初的猜测是Master 认为取消流程已经处理完毕但 Worker 实际上从未收到 Cancel 请求。这个方向确实值得关注。不过后来我发现仅凭这一点还不足以解释为什么 Job 会一直停留在 CANCELING 状态。因为即便错过了 Cancel 请求任务最终仍有可能正常结束并将最终状态上报给 Master。于是我开始把视线转向另一个方向当 Worker 向 Master 汇报最终任务状态时究竟会发生什么更关键的链路Worker → Master 的状态通知当任务进入最终状态后Worker 会调用notifyTaskStatusToMaster()将状态上报给 Master。该方法的设计思路是在通知成功之前持续进行重试。while (isRunning !notifyStateSuccess) { InvocationFutureObject invoke nodeEngine .getOperationService() .createInvocationBuilder( SeaTunnelServer.SERVICE_NAME, new NotifyTaskStatusOperation( taskGroupLocation, taskExecutionState), nodeEngine.getMasterAddress()) .invoke(); try { invoke.get(); notifyStateSuccess true; } catch (JobNotFoundException e) { notifyStateSuccess true; } catch (ExecutionException e) { if (e.getCause() instanceof JobNotFoundException) { notifyStateSuccess true; } else { Thread.sleep(sleepTime); } } }乍看之下这套重试机制本身并没有什么问题。但其中对JobNotFoundException的处理却至关重要。如果 Worker 收到JobNotFoundException它会将notifyStateSuccess设为true并停止后续重试。在很多情况下这样的处理是合理的。因为如果 Master 上已经找不到对应的 Job往往意味着该 Job 已经结束并且已经从运行中的 Job 列表中移除。但在 Master Failover 场景下这种假设就可能带来问题。JobNotFoundException 的特殊处理逻辑在 Master 端任务状态更新时会先检查runningJobMasterMappublic void updateTaskExecutionState(TaskExecutionState taskExecutionState) { TaskGroupLocation taskGroupLocation taskExecutionState.getTaskGroupLocation(); JobMaster runningJobMaster runningJobMasterMap.get(taskGroupLocation.getJobId()); if (runningJobMaster null) { throw new JobNotFoundException( String.format(Job %s not running, taskGroupLocation.getJobId())); } runningJobMaster.updateTaskExecutionState(taskExecutionState); }通常情况下runningJobMaster null表示该 Job 已经不再运行。然而还有另一种可能的时间窗口。在 Master Failover 期间新的 Master 可能尚未完全恢复runningJobMasterMap。如果 Worker 恰好在这段时间内上报最终任务状态新 Master 就可能无法找到对应的JobMaster并抛出JobNotFoundException。随后Worker 会将这个异常视为成功处理并停止重试。问题发生的过程可能如下一个 Job 正在执行取消操作。Master 发生切换。Worker 完成任务并上报最终任务状态。新 Master 尚未完全恢复runningJobMasterMap。Master 抛出JobNotFoundException。Worker 将其视为成功处理并停止重试。Master 在恢复完成后始终没有收到最终任务状态。Job 一直停留在CANCELING状态。这正是我发现问题的关键。问题不仅仅在于 Cancel RPC 可能发送失败更重要的是Worker 的最终状态通知有可能在 Master 恢复期间丢失。为什么我选择新增 Force Stop而不是直接修改 Cancel定位到问题后我考虑过几种不同的解决方案调整 JobNotFoundException 的处理逻辑等待 runningJobMasterMap 完全恢复后再处理状态通知将更多运行时状态持久化到分布式存储重构现有的 Cancel 状态机。但这个问题具有偶发性而且高度依赖特定的时序条件。与此同时正常的 Cancel 流程又是整个执行生命周期中非常敏感的一部分。直接修改这部分逻辑可能会引入新的行为变化或者带来额外的性能开销。因此我首先选择了一种更务实的方案。我没有改变现有 Cancel 的语义而是新增了一套独立的 Force Stop 机制。思路其实很简单如果优雅取消Graceful Cancellation无法继续推进那么运维人员就需要一种明确的手段来最终确定 Job 的状态。Cancel 与 Force Stop 的区别让我来解释下 Cancel 与 Force Stop 的区别。CancelCancel 属于一种优雅终止Graceful Shutdown机制。它会向正在运行的任务发送停止请求并依赖正常的任务生命周期以及 Worker 的状态通知链路来完成整个过程。Force StopForce Stop 则是一种面向运维恢复的机制。它不应该依赖远端 Worker 是否仍然能够正常响应。Master 会根据自身的判断直接完成 Job 状态的终结和相关资源的清理。简单来说Cancel 尝试以优雅的方式停止 Job Force Stop 当 Cancel 无法继续推进时直接终结 JobForce Stop 的目的并不是取代 Cancel。它是一条专门用于处理卡死场景的兜底路径。我的收获这次问题让我意识到一个 Job 状态卡住并不一定是负责更新该状态的那段代码出了问题。在这个案例中一开始最可疑的是 Cancel 请求链路。但最终发现更关键的问题其实出在 Worker 到 Master 的状态通知链路上。在正常情况下JobNotFoundException看起来是一个合理的终止条件但在 Master Failover 场景下它也可能意味着新的 Master 尚未完成 Job 的恢复。这两种含义有着本质区别。而这样一个细微的差别恰恰决定了 Worker 应该停止重试还是继续重试。这也再次提醒我在分布式系统中异常处理本身就是状态机的一部分而不仅仅是错误处理逻辑。总结
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/4 15:56:54

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/3 12:09:35

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/4 17:01:23

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/4 12:33:12

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/4 1:25:31

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/4 3:51:11

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉