YARN源码不知从何入手,那是你不知道Service

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

推荐阅读时间:10分钟

字数:1357字

YARN Server工作机制深度剖析

YARN的核心设计理念是服务化(Service)事件驱动AsyncDispatcher ( Event + EventHandler/StateMachine) 。服务化和事件驱动软件设计思想的引入,使得YARN具有低耦合、高内聚的特点,各个模块只需完成各自功能,而模块之间则采用事件联系起来,系统设计简单且维护方便。这种编程方式具有异步、并发等特点,更高效,更适合大型分布式系统。

Service在Yarn源码中处处可见,想要阅读源码就得选了解YARN中的Service机制

下面就详细介绍下什么是Service

对于生命周期较长的对象,YARN 采用了基于服务的对象管理模型对其进行管理,该模型主要有以下几个特点。

  • 将每个被服务化的对象分为 4 个状态:NOTINITED(被创建)、INITED(已初始化)、STARTED(已启动)、STOPPED(已停止)。
  • 任何服务状态变化都可以触发另外一些动作。
  • 可通过组合的方式对任意服务进行组合,以便进行统一管理。通俗的解释:一个大 Service 可能会有一堆子 Service

使用场景化驱动的方式来了解YARN Service

我们比较熟悉的ResourceManager其实就是一个Service,它本身就是Service的子类,下面是ResourceManager和NodeManager类的继承类图:

根据类的继承关系,直接看接口Service,接口的具体信息如下:

  • 印证了Service都有四个状态:NOTINITED、INITED、STARTED、STOPPED
  • 于此同时还有五个重要的方法:构造方法、init()、start()、stop()、close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码public interface Service extends Closeable { 
public enum STATE {
NOTINITED(0, "NOTINITED"),
INITED(1, "INITED"),
STARTED(2, "STARTED"),
STOPPED(3, "STOPPED");
}
// 服务初始化
void init(Configuration config);
// 服务启动
void start();
// 服务停止
void stop();
// 服务关闭
void close() throws IOException;
}

这四个状态和五个重要的方法之间有不可分割的关系:

了解了Service的主要信息之后,下面从上往下查看各类的具体信息

对于AbstractService类,它实现了结构Service,那么它一定会对上述的四个方法进行实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码public abstract class AbstractService implements Service { 
private final String name;
private final ServiceStateModel stateModel;

@Override public void init(Configuration conf) { serviceInit(config); }

@Override public void start() { serviceStart(); }

@Override public void stop() { serviceStop(); }

// 都是空实现!
protected void serviceInit() throws Exception {}
protected void serviceStart() throws Exception { }
protected void serviceStop() throws Exception { }
}

通过源码可以看到,虽然对四个方法都已经进行了实现但是都是空实现,这是为什么呢?

使用一个中间类去对父类的方法进行空实现,然后真正的子类去继承中间类,这样可以避免子类去实现父类的一些不必要的方法,此处AbstractService就是中间类,这样的代码设计模式是可以借鉴的

既然AbstractService对这四个方法没有进行实现,下面就来看它的子类CompositeService,来看CompositeService类的具体定义:

  1. 一个ArrayList,它是一个Service类型的集合,印证了上面的特点:一个大 Service 可能会有一堆子 Service

此处是ArrayList说明Service加入的顺序是保留了下来的,是有顺序的

1
java复制代码private final List<Service> serviceList = new ArrayList<Service>();
  1. 从ArrayList中获取Service,上述已经说明列表保留了服务的顺序,由此此处获取Service也是有顺序的
1
2
3
4
5
java复制代码public List<Service> getServices() { 
synchronized(serviceList) {
return new ArrayList<Service>(serviceList);
}
}
  1. 添加子 service 的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码protected void addService(Service service) { 
synchronized(serviceList) {
serviceList.add(service);
}
}
protected boolean addIfService(Object object) {
if(object instanceof Service) {
addService((Service) object);
return true;
} else {
return false;
}
}
  1. 针对所有 Service 执行 init 初始化:最终调用 service 的 () 方法

针对所有 Service 执行 start 启动:最终调用 service 的 serviceStart() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码protected void serviceInit(Configuration conf) throws Exception { 
// 获取当前 service 组件的所有子 service
List<Service> services = getServices();
// 遍历每个 子 service 调用 init() 执行初始化
for(Service service : services) {
service.init(conf);
}
}

protected void serviceStart() throws Exception {
List<Service> services = getServices();
for(Service service : services) {
service.start();
}
}

下面看到ResourceManager,它是CompositeService的子类,它实现了方法serviceInit()、serviceStart()、serviceStop()

当ResourceManager进行初始化、开启的时候会调用父类的init、start方法,然后这两个方法再调用本部类重写了的serviceInit()、serviceStart()方法,从而完成具体业务逻辑。

1
2
3
4
5
6
7
8
9
10
java复制代码ResourceManager.main(){
// ResourceManager 初始化
Resourcemanager resourceManager = new Resourcemanager();

// 各种服务创建和初始化
resourceManage.init(conf);

//各种服务启动
resourcemanager.start();
}

总而言之,在 YARN 中,会有非常非常多的 Service,每个 service 都要初始化和启动,如果Service本身有serviceInit、serviceStart方法,就各自做自己的实现,否则使用父类的实现。

如果阅读 Service 组件的源码,从下面三方面入手:

  • 构造方法
  • serviceInit() 方法
  • serviceStart() 方法

本人在学习的路上,上述文章如有错误还请指教批评。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%