

【深入浅出 Yarn 架构与实现】2-4 Yarn 基础库 - 状态机库 - 大数据王小皮
source link: https://www.cnblogs.com/shuofxz/p/16881989.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

当一个服务拥有太多处理逻辑时,会导致代码结构异常的混乱,很难分辨一段逻辑是在哪个阶段发挥作用的。
这时就可以引入状态机模型,帮助代码结构变得清晰。
一、状态机库概述
状态机由一组状态组成:
【初始状态 -> 中间状态 -> 最终状态】。
在一个状态机中,每个状态会接收一组特定的事件,根据事件类型进行处理,并转换到下一个状态。当转换到最终状态时则退出。
二)状态转换方式
三)Yarn 状态机类
在 Yarn 中提供了一个工厂类 StateMachineFactory
来帮助定义状态机。如何使用,我们直接写个 demo。
二、案例 demo
在上一篇文章《Yarn 服务库和事件库》案例基础上进行扩展,增加状态机库的内容。如果还不了解服务库和事件库的同学,建议先学习下上一篇文章。
案例已上传至 github,有帮助可以点个 ⭐️
https://github.com/Simon-Ace/hadoop-yarn-study-demo/tree/master/state-demo
一)状态机实现
状态机实现,可以直接嵌入到上篇文章中的 AsyncDispatcher
使用。
这里仅给出状态机JobStateMachine
以及各种事件处理的代码。完整的代码项目执行,请到 github demo 中查看。
import com.shuofxz.event.JobEvent;
import com.shuofxz.event.JobEventType;
import org.apache.hadoop.yarn.event.EventHandler;
import org.apache.hadoop.yarn.state.*;
import java.util.EnumSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*
* 可参考 Yarn 中实现的状态机对象:
* ResourceManager 中的 RMAppImpl、RMApp- AttemptImpl、RMContainerImpl 和 RMNodeImpl,
* NodeManager 中 的 ApplicationImpl、 ContainerImpl 和 LocalizedResource,
* MRAppMaster 中的 JobImpl、TaskImpl 和 TaskAttemptImpl 等
* */
@SuppressWarnings({"rawtypes", "unchecked"})
public class JobStateMachine implements EventHandler<JobEvent> {
private final String jobID;
private EventHandler eventHandler;
private final Lock writeLock;
private final Lock readLock;
// 定义状态机
protected static final StateMachineFactory<JobStateMachine, JobStateInternal,
JobEventType, JobEvent>
stateMachineFactory = new StateMachineFactory<JobStateMachine, JobStateInternal, JobEventType, JobEvent>(JobStateInternal.NEW)
.addTransition(JobStateInternal.NEW, JobStateInternal.INITED, JobEventType.JOB_INIT, new InitTransition())
.addTransition(JobStateInternal.INITED, JobStateInternal.SETUP, JobEventType.JOB_START, new StartTransition())
.addTransition(JobStateInternal.SETUP, JobStateInternal.RUNNING, JobEventType.JOB_SETUP_COMPLETED, new SetupCompletedTransition())
.addTransition(JobStateInternal.RUNNING, EnumSet.of(JobStateInternal.KILLED, JobStateInternal.SUCCEEDED), JobEventType.JOB_COMPLETED, new JobTasksCompletedTransition())
.installTopology();
private final StateMachine<JobStateInternal, JobEventType, JobEvent> stateMachine;
public JobStateMachine(String jobID, EventHandler eventHandler) {
this.jobID = jobID;
// 多线程异步处理,state 有可能被同时读写,使用读写锁来避免竞争
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
this.readLock = readWriteLock.readLock();
this.writeLock = readWriteLock.writeLock();
this.eventHandler = eventHandler;
stateMachine = stateMachineFactory.make(this);
}
protected StateMachine<JobStateInternal, JobEventType, JobEvent> getStateMachine() {
return stateMachine;
}
public static class InitTransition implements SingleArcTransition<JobStateMachine, JobEvent> {
@Override
public void transition(JobStateMachine jobStateMachine, JobEvent jobEvent) {
System.out.println("Receiving event " + jobEvent);
// do something...
// 完成后发送新的 Event —— JOB_START
jobStateMachine.eventHandler.handle(new JobEvent(jobStateMachine.jobID, JobEventType.JOB_START));
}
}
public static class StartTransition implements SingleArcTransition<JobStateMachine, JobEvent> {
@Override
public void transition(JobStateMachine jobStateMachine, JobEvent jobEvent) {
System.out.println("Receiving event " + jobEvent);
jobStateMachine.eventHandler.handle(new JobEvent(jobStateMachine.jobID, JobEventType.JOB_SETUP_COMPLETED));
}
}
public static class SetupCompletedTransition implements SingleArcTransition<JobStateMachine, JobEvent> {
@Override
public void transition(JobStateMachine jobStateMachine, JobEvent jobEvent) {
System.out.println("Receiving event " + jobEvent);
jobStateMachine.eventHandler.handle(new JobEvent(jobStateMachine.jobID, JobEventType.JOB_COMPLETED));
}
}
public static class JobTasksCompletedTransition implements MultipleArcTransition<JobStateMachine, JobEvent, JobStateInternal> {
@Override
public JobStateInternal transition(JobStateMachine jobStateMachine, JobEvent jobEvent) {
System.out.println("Receiving event " + jobEvent);
// 这是多结果状态部分,因此需要人为制定后续状态
// 这里整个流程结束,设置一下对应的状态
boolean flag = true;
if (flag) {
return JobStateInternal.SUCCEEDED;
} else {
return JobStateInternal.KILLED;
}
}
}
@Override
public void handle(JobEvent jobEvent) {
try {
// 注意这里为了避免静态条件,使用了读写锁
writeLock.lock();
JobStateInternal oldState = getInternalState();
try {
getStateMachine().doTransition(jobEvent.getType(), jobEvent);
} catch (InvalidStateTransitionException e) {
System.out.println("Can't handle this event at current state!");
}
if (oldState != getInternalState()) {
System.out.println("Job Transitioned from " + oldState + " to " + getInternalState());
}
} finally {
writeLock.unlock();
}
}
public JobStateInternal getInternalState() {
readLock.lock();
try {
return getStateMachine().getCurrentState();
} finally {
readLock.unlock();
}
}
public enum JobStateInternal {
NEW,
SETUP,
INITED,
RUNNING,
SUCCEEDED,
KILLED
}
}
二)状态机可视化
hadoop 中提供了状态机可视化的工具类 VisualizeStateMachine.java
,可以拷贝到我们的工程中使用。
根据提示,运行需要三个参数:
Usage: %s <GraphName> <class[,class[,...]]> <OutputFile>%n
运行后会在项目根目录生成图文件 jsm.gv
。
需要使用 graphviz
工具将 gv 文件转换成 png 文件:
# linux 安装
yum install graphviz
# mac 安装
brew install graphviz
dot -Tpng jsm.gv > jsm.png
可视化状态机展示:
再使用这个工具对 Yarn 中的 Application 状态进行展示:
三)如果不用状态机库
【思考】
如果不用状态机,代码结构会是什么样呢?
下面这样的代码,如果要增加或修改逻辑可能就是很痛苦的一件事情了。
// 一堆的函数调用
// 一堆的 if 嵌套
// 或者 switch case
本节对 Yarn 状态机库进行了介绍。实际使用时会结合事件库、服务库一同使用。
状态机库的使用帮助代码结构更加的清晰,新增状态处理逻辑只需要增加一个状态类别,或者增加一个方法处理对应类型的事件即可。将整个处理逻辑进行了拆分,便于编写和维护。
参考文章:
源码|Yarn的事件驱动模型与状态机
__EOF__
Recommend
-
2
了解 Yarn 基础库是后面阅读 Yarn 源码的基础,本节对 Yarn 基础库做总体的介绍。并对其中使用的第三方库 Protocol Buffers 和 Avro 是什么、怎么用做简要的介绍。 一、主要使用的库 Protocol Buffers
-
3
RPC(Remote Procedure Call) 是 Hadoop 服务通信的关键库,支撑上层分布式环境下复杂的进程间(Inter-Process Communication, IPC)通信逻辑,是分布式系统的基础。允许运行于一台计算机上的程序像调用本地方法一样,调用另一台计算机的子程序。由于 RPC 服...
-
6
一个庞大的分布式系统,各个组件间是如何协调工作的?组件是如何解耦的?线程运行如何更高效,减少阻塞带来的低效问题?本节将对 Yarn 的服务库和事件库进行介绍,看看 Yarn 是如何解决这些问题的。 一、服务库 对于生命周期较长的对...
-
14
本篇文章继续介绍 Yarn Application 中 ApplicationMaster 部分的编写方法。 一、Application Master 编写方法 上一节讲了 Client 提交任务给 RM 的全流程,RM 收到任务后,由 ApplicationsManager...
-
9
前面几篇文章对 Yarn 基本架构、程序基础库、应用设计方法等进行了介绍。之后几篇将开始对 Yarn 核心组件进行剖析。 ResourceManager(RM)是 Yarn 的核心管理服务,负责集群管理、任务调度、状态机管理等,本篇将对 RM 总体架构进行介绍。
-
13
本篇继续对 RM 中管理 NodeManager 的部分进行深入的讲解。主要有三个部分:检查 NM 是否存活;管理 NM 的黑白名单;响应 NM RPC 请求。 一、简介
-
10
在 YARN 中,Application 是指应用程序,它可能启动多个运行实例,每个运行实例由 —个 ApplicationMaster 与一组该 ApplicationMaster 启动的任务组成,它拥有名称、队列、优先级等属性,是一个比较宽泛的概念,可以是一个 MepReduce 作业、一个 DAG 应用程序等。YAR...
-
3
新浪VR > 正文页 昊舜视讯|HVC-M300通用型车载无人机库...
-
8
本节开始将对 Yarn 中的 NodeManager 服务进行剖析。 NodeManager 需要在每个计算节点上运行,与 ResourceManager 和 ApplicationMaster 进行交互。管理节点的计算资源以及调度容器。后续将对 NM 的功能职责、状态机、容器生命周期和资源隔离等方面进行讲解。...
-
2
一、简介# NodeManager(NM)中的状态机分为三类:Application、Container 和 LocalizedResource,它们均直接或者间接参与维护一...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK