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()

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,那么它一定会对上述的四个方法进行实现

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加入的顺序是保留了下来的,是有顺序的

private final List<Service> serviceList = new ArrayList<Service>();
复制代码
  1. 从ArrayList中获取Service,上述已经说明列表保留了服务的顺序,由此此处获取Service也是有顺序的
public List<Service> getServices() { 
    synchronized(serviceList) { 
        return new ArrayList<Service>(serviceList); 
    } 
}
复制代码
  1. 添加子 service 的方法
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() 方法

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()方法,从而完成具体业务逻辑。

ResourceManager.main(){
// ResourceManager 初始化
Resourcemanager resourceManager = new Resourcemanager();
    
// 各种服务创建和初始化
resourceManage.init(conf);
    
//各种服务启动
resourcemanager.start();
}
复制代码

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

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

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

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

猜你喜欢

转载自juejin.im/post/7033195990957948936