Yarn的服务化框架分析
文章目录
服务化指什么
将yarn中众多的功能拆分为众多的服务,按照定义好的服务框架(规范)进行组织管理。通过Service框架进行服务的管理,通过抽象的Service接口表示抽象的服务。
服务化有什么
Yarn提供的每个服务都有一种状态(STATE),可对服务进行初始化/启动/停止操作。
服务的状态
NOTINITED
,其值为0
,代表服务尚未初始化INITED
,其值为1
,代表服务已经完成初始化STARTED
,其值为2
,代表服务已经启动STOPPED
,其值为3
,代表服务已经停止
服务状态的转换方法
-
init
方法的目标是使服务从NOINITED -> INITED
进行状态转换 -
start
方法的目标是使服务从INITED -> STARTED
进行状态转换 -
stop
方法的目标是使服务从STARTED->STOPPED
进行状态转换
服务的状态不是随意转换的,需要满足转换要求,通过ServiceStateModel
中的二维数组statemap来巧妙控制状态的合理转换,
java
private static final boolean[][] statemap =
{
// uninited inited started stopped
/* uninited */ {false, true, false, true},
/* inited */ {false, true, true, true},
/* started */ {false, false, true, true},
/* stopped */ {false, false, false, true},
};
横轴代表旧状态,竖轴代表新状态,其数组的值代表是否可以从此旧状态转换到新状态。
服务框架的实现
服务化采用了模板方面模式,将服务状态变化的相关方法抽象到了抽象类AbstractService
中,具体服务的开发的时候,只需要关注具体逻辑,不需要重复写状态转换的代码了。AbstractService
类只能表示一个独立的Service,并不能表示所有服务。为了满足某一个服务中包含其他子服务管理的场景,提供了CompositeService
类,来管理所有子服务服务群组的状态转换方法。
以ResourceManager
为例简化的类图如下:
implements extends extends extends extends extends <<interface>> Serivce #void init(Configuration config) #void start() #void stop() <<enumeration>> STATE NOTINITED INITED STARTED STOPPED <<Abstract>> AbstractService - String name - ServiceStateModel stateModel; +void init(Configuration conf) +void start() +void stop() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop() CompositeService - List serviceList - ServiceStateModel stateModel; +synchronized boolean removeService(Service service) +void addService(Service service) +List getServices() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop() ServiceStateModel - volatile STATE state - String name - static final boolean[][] statemap +synchronized STATE enterState(STATE proposed) +static isValidStateTransition(STATE current,STATE proposed) +getState() +boolean isInState(STATE proposed) +void ensureCurrentState(STATE expectedState) ResourceManager - Configuration conf # AdminService adminService # AsyncDispatcher asyncDispatcher # RMApplicationHistoryWriter rmApplicationHistoryWriter +ResourceManager() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop() +main(String argv[]) AdminService +AdminService() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop() RMApplicationHistoryWriter +RMApplicationHistoryWriter() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop() AsyncDispatcher +AsyncDispatcher() #void serviceInit(Configuration conf) #void serviceStart() #void serviceStop()
实验
入口方法是ResourceManager
类的main
方法,
执行结果
log
ResourceManager State is changed to INITED
ResourceManager serviceStart
Adding service AdminService
Adding service Dispatcher
Adding service RMApplicationHistoryWriter
ResourceManager: initing services, size=3
AdminService State is changed to INITED
AdminService serviceInit
AdminService: initing services, size=0
AbstractService serviceInit
AdminService 初始化状态成功,做些其他关联的事情
Dispatcher State is changed to INITED
AsyncDispatcher serviceInit
AbstractService serviceInit
Dispatcher 初始化状态成功,做些其他关联的事情
RMApplicationHistoryWriter State is changed to INITED
RMApplicationHistoryWriter serviceInit
RMApplicationHistoryWriter: initing services, size=0
AbstractService serviceInit
RMApplicationHistoryWriter 初始化状态成功,做些其他关联的事情
AbstractService serviceInit
ResourceManager 初始化状态成功,做些其他关联的事情
ResourceManager serviceStart
ResourceManager: starting services, size=3
AdminService serviceStart
AdminService: starting services, size=0
AbstractService serviceStart
AdminService 服务启动成功,做些其他关联的事情
AsyncDispatcher serviceStart
AbstractService serviceStart
Dispatcher 服务启动成功,做些其他关联的事情
RMApplicationHistoryWriter serviceStart
RMApplicationHistoryWriter: starting services, size=0
AbstractService serviceStart
RMApplicationHistoryWriter 服务启动成功,做些其他关联的事情
AbstractService serviceStart
ResourceManager 服务启动成功,做些其他关联的事情
伪装常驻5s等待关闭
ResourceManager State is changed to STOPPED
ResourceManager serviceStop
ResourceManager: stopping services, size=3
Stopping service #2: com.donny.service.RMApplicationHistoryWriter@330bedb4
RMApplicationHistoryWriter State is changed to STOPPED
RMApplicationHistoryWriter serviceStop
RMApplicationHistoryWriter: stopping services, size=0
AbstractService serviceStop
RMApplicationHistoryWriter report stop, notify anything listening for events
Stopping service #1: com.donny.service.AsyncDispatcher@2503dbd3
Dispatcher State is changed to STOPPED
AsyncDispatcher serviceStop
AbstractService serviceStop
Dispatcher report stop, notify anything listening for events
Stopping service #0: com.donny.service.AdminService@4b67cf4d
AdminService State is changed to STOPPED
AdminService serviceStop
AdminService: stopping services, size=0
AbstractService serviceStop
AdminService report stop, notify anything listening for events
AbstractService serviceStop
ResourceManager report stop, notify anything listening for events
通过日志可以发现,以RM为主服务时,在初始化和启动子服务的时候,是按照子服务的添加到服务群组的顺序启动的,而关闭服务的时候按其子服务添加顺序的倒序进行关闭的。由RM触发服务群组的初始化、启动和关闭,当整个服务群组完成状态转换后,才是RM整个主服务状态转换完成。
具体代码
service类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public interface Service {
boolean isInState(STATE expected);
STATE getServiceState();
void init(Configuration config);
void start();
void stop();
String getName();
}
STATE类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public enum STATE {
NOTINITED(0, "NOTINITED"),
INITED(1, "INITED"),
STARTED(2, "STARTED"),
STOPPED(3, "STOPPED");
private final int value;
private final String statename;
private STATE(int value, String name) {
this.value = value;
this.statename = name;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return statename;
}
}
ServiceStateModel类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class ServiceStateModel {
private static final boolean[][] statemap =
{
// uninited inited started stopped
/* uninited */ {false, true, false, true},
/* inited */ {false, true, true, true},
/* started */ {false, false, true, true},
/* stopped */ {false, false, false, true},
};
private volatile STATE state;
private String name;
public ServiceStateModel(String name) {
this(name, STATE.NOTINITED);
}
public ServiceStateModel(String name, STATE state) {
this.state = state;
this.name = name;
}
public STATE getState() {
return state;
}
public boolean isInState(STATE proposed) {
return state.equals(proposed);
}
public void ensureCurrentState(STATE expectedState) {
if (state != expectedState) {
throw new ServiceStateException(name + ": for this operation, the " +
"current service state must be "
+ expectedState
+ " instead of " + state);
}
}
public synchronized STATE enterState(STATE proposed) {
checkStateTransition(name, state, proposed);
STATE oldState = state;
//atomic write of the new state
state = proposed;
return oldState;
}
public static void checkStateTransition(String name,
STATE state,
STATE proposed) {
if (!isValidStateTransition(state, proposed)) {
throw new ServiceStateException(name + " cannot enter state "
+ proposed + " from state " + state);
}
}
public static boolean isValidStateTransition(STATE current,
STATE proposed) {
boolean[] row = statemap[current.getValue()];
return row[proposed.getValue()];
}
@Override
public String toString() {
return (name.isEmpty() ? "" : ((name) + ": "))
+ state.toString();
}
}
AbstractService类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public abstract class AbstractService implements Service {
private final String name;
private final ServiceStateModel stateModel;
private final Object stateChangeLock = new Object();
private volatile Configuration config;
@Override
public String getName() {
return name;
}
public AbstractService(String name) {
this.name = name;
stateModel = new ServiceStateModel(name);
}
protected void setConfig(Configuration conf) {
this.config = conf;
}
protected void serviceInit(Configuration conf) throws Exception {
if (conf != config) {
System.out.println("更新配置");
setConfig(conf);
}
System.out.println("AbstractService serviceInit");
}
@Override
public final boolean isInState(STATE expected) {
return stateModel.isInState(expected);
}
@Override
public final STATE getServiceState() {
return stateModel.getState();
}
private STATE enterState(STATE newState) {
assert stateModel != null : "null state in " + name + " " + this.getClass();
STATE oldState = stateModel.enterState(newState);
if (oldState != newState) {
// do something,eg:log
System.out.println(getName() + " State is changed to " + newState.name());
}
return oldState;
}
@Override
public void init(Configuration conf) {
if (conf == null) {
throw new ServiceStateException("Cannot initialize service "
+ getName() + ": null configuration");
}
if (isInState(STATE.INITED)) {
return;
}
synchronized (stateChangeLock) {
if (enterState(STATE.INITED) != STATE.INITED) {
setConfig(conf);
try {
serviceInit(config);
if (isInState(STATE.INITED)) {
//if the service ended up here during init,
//notify the listeners
System.out.println(getName() + " 初始化状态成功,做些其他关联的事情");
}
} catch (Exception e) {
// 做一些失败补偿操作
System.out.println("init is Exception.");
throw new ServiceStateException(e);
}
}
}
}
@Override
public void start() {
if (isInState(STATE.STARTED)) {
return;
}
//enter the started state
synchronized (stateChangeLock) {
if (stateModel.enterState(STATE.STARTED) != STATE.STARTED) {
try {
serviceStart();
System.out.println(getName() + " 服务启动成功,做些其他关联的事情");
} catch (Exception e) {
// 做一些失败补偿操作
System.out.println("start is Exception.");
throw new ServiceStateException(e);
}
}
}
}
protected void serviceStart() throws Exception {
System.out.println("AbstractService serviceStart");
}
/**
* {@inheritDoc}
*/
@Override
public void stop() {
if (isInState(STATE.STOPPED)) {
return;
}
synchronized (stateChangeLock) {
if (enterState(STATE.STOPPED) != STATE.STOPPED) {
try {
serviceStop();
} catch (Exception e) {
// 做一些失败补偿操作
System.out.println(getName() + " stop is Exception.");
throw new ServiceStateException(e);
} finally {
//report that the service has terminated
//notify anything listening for events
System.out.println(getName() + " report stop, notify anything listening for events");
}
} else {
System.out.println("服务已经是停止状态.");
}
}
}
protected void serviceStop() throws Exception {
System.out.println("AbstractService serviceStop");
}
}
CompositeService类
java
package com.donny.service;
import java.util.ArrayList;
import java.util.List;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class CompositeService extends AbstractService {
protected static final boolean STOP_ONLY_STARTED_SERVICES = false;
private final List<Service> serviceList = new ArrayList<Service>();
public CompositeService(String name) {
super(name);
}
public List<Service> getServices() {
synchronized (serviceList) {
return new ArrayList<Service>(serviceList);
}
}
protected void addService(Service service) {
System.out.println("Adding service " + service.getName());
synchronized (serviceList) {
serviceList.add(service);
}
}
protected boolean addIfService(Object object) {
if (object instanceof Service) {
addService((Service) object);
return true;
} else {
return false;
}
}
protected synchronized boolean removeService(Service service) {
synchronized (serviceList) {
return serviceList.remove(service);
}
}
protected void serviceInit(Configuration conf) throws Exception {
List<Service> services = getServices();
System.out.println(getName() + ": initing services, size=" + services.size());
for (Service service : services) {
service.init(conf);
}
super.serviceInit(conf);
}
protected void serviceStart() throws Exception {
List<Service> services = getServices();
System.out.println(getName() + ": starting services, size=" + services.size());
for (Service service : services) {
// start the service. If this fails that service
// will be stopped and an exception raised
service.start();
}
super.serviceStart();
}
protected void serviceStop() throws Exception {
//stop all services that were started
int numOfServicesToStop = serviceList.size();
System.out.println(getName() + ": stopping services, size=" + numOfServicesToStop);
stop(numOfServicesToStop, STOP_ONLY_STARTED_SERVICES);
super.serviceStop();
}
private void stop(int numOfServicesStarted, boolean stopOnlyStartedServices) {
// stop in reverse order of start
Exception firstException = null;
List<Service> services = getServices();
for (int i = numOfServicesStarted - 1; i >= 0; i--) {
Service service = services.get(i);
System.out.println("Stopping service #" + i + ": " + service);
STATE state = service.getServiceState();
//depending on the stop police
if (state == STATE.STARTED
|| (!stopOnlyStartedServices && state == STATE.INITED)) {
Exception ex = ServiceOperations.stopQuietly(service);
if (ex != null && firstException == null) {
firstException = ex;
}
}
}
//after stopping all services, rethrow the first exception raised
if (firstException != null) {
throw new ServiceStateException(firstException);
}
}
}
ServiceStateException类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class ServiceStateException extends RuntimeException {
public ServiceStateException() {
super();
}
public ServiceStateException(String msg) {
super(msg);
}
public ServiceStateException(String msg, Throwable cause) {
super(msg, cause);
}
public ServiceStateException(Throwable cause) {
super(cause);
}
}
ServiceOperations类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class ServiceOperations {
private ServiceOperations() {
}
public static void stop(Service service) {
if (service != null) {
service.stop();
}
}
public static Exception stopQuietly(Service service) {
try {
stop(service);
} catch (Exception e) {
System.out.println("When stopping the service " + service.getName()
+ " : " + e);
return e;
}
return null;
}
}
AdminService类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class AdminService extends CompositeService {
public AdminService() {
super("AdminService");
}
@Override
protected void serviceInit(Configuration conf) throws Exception {
System.out.println("AdminService serviceInit");
super.serviceInit(conf);
}
@Override
protected void serviceStart() throws Exception {
System.out.println("AdminService serviceStart");
super.serviceStart();
}
@Override
protected void serviceStop() throws Exception {
System.out.println("AdminService serviceStop");
super.serviceStop();
}
}
AsyncDispatcher类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class AsyncDispatcher extends AbstractService {
public AsyncDispatcher() {
super("Dispatcher");
}
@Override
protected void serviceInit(Configuration conf) throws Exception {
System.out.println("AsyncDispatcher serviceInit");
super.serviceInit(conf);
}
@Override
protected void serviceStart() throws Exception {
//start all the components
System.out.println("AsyncDispatcher serviceStart");
super.serviceStart();
}
@Override
protected void serviceStop() throws Exception {
System.out.println("AsyncDispatcher serviceStop");
super.serviceStop();
}
}
RMApplicationHistoryWriter类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class RMApplicationHistoryWriter extends CompositeService {
public RMApplicationHistoryWriter() {
super("RMApplicationHistoryWriter");
}
@Override
protected void serviceInit(Configuration conf) throws Exception {
System.out.println("RMApplicationHistoryWriter serviceInit");
super.serviceInit(conf);
}
@Override
protected void serviceStart() throws Exception {
System.out.println("RMApplicationHistoryWriter serviceStart");
super.serviceStart();
}
@Override
protected void serviceStop() throws Exception {
System.out.println("RMApplicationHistoryWriter serviceStop");
super.serviceStop();
}
}
Configuration类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class Configuration {
public String getCustomConfig() {
return customConfig;
}
public void setCustomConfig(String customConfig) {
this.customConfig = customConfig;
}
private String customConfig;
}
ResourceManager类
java
package com.donny.service;
/**
* @author [email protected]
* @description
* @date 2023/9/18
*/
public class ResourceManager extends CompositeService {
private Configuration conf;
protected AdminService adminService;
protected AsyncDispatcher asyncDispatcher;
protected RMApplicationHistoryWriter rmApplicationHistoryWriter;
public ResourceManager() {
super("ResourceManager");
}
protected void serviceInit(Configuration conf) throws Exception {
System.out.println("ResourceManager serviceStart");
this.conf = conf;
adminService = new AdminService();
asyncDispatcher = new AsyncDispatcher();
rmApplicationHistoryWriter = new RMApplicationHistoryWriter();
addService(adminService);
addIfService(asyncDispatcher);
addService(rmApplicationHistoryWriter);
super.serviceInit(this.conf);
}
@Override
protected void serviceStart() throws Exception {
//start all the components
System.out.println("ResourceManager serviceStart");
super.serviceStart();
}
@Override
protected void serviceStop() throws Exception {
System.out.println("ResourceManager serviceStop");
super.serviceStop();
}
public static void main(String argv[]) throws Exception {
ResourceManager resourceManager = new ResourceManager();
Configuration configuration = new Configuration();
configuration.setCustomConfig("自定义配置");
resourceManager.setConfig(configuration);
resourceManager.init(configuration);
resourceManager.start();
System.out.println("伪装常驻5s等待关闭");
Thread.sleep(5000);
resourceManager.stop();
}
}