org.apache.hadoop.yarn.server.resourcemanager.ResourceManager类main()分析
public static void main(String argv[]) {
//为主线程注册一个UncaughtException处理器,设置在线程因未捕获异常而突
//然终止时调用的默认处理程序
Thread.setDefaultUncaughtExceptionHandler(new YarnUncaughtExceptionHandler());
//server启动和终止是打印相应的日志(终止日志打印是通过addShutdownHook来完成的)
StringUtils.startupShutdownMessage(ResourceManager.class, argv, LOG);
try {
//加载配置文件:core-default.xml,core-site.xml,yarn-default.xml,yarn-site.xml
Configuration conf = new YarnConfiguration();
GenericOptionsParser hParser = new GenericOptionsParser(conf, argv);
argv = hParser.getRemainingArgs();
// If -format-state-store, then delete RMStateStore; else startup normally TODO:实现分析
if (argv.length == 1 && argv[0].equals("-format-state-store")) {
deleteRMStateStore(conf);
} else {
//构造RM对象,
ResourceManager resourceManager = new ResourceManager();
//添加一个shutdownHook,用来停止服务的所有资源
ShutdownHookManager.get().addShutdownHook(
new CompositeServiceShutdownHook(resourceManager),
SHUTDOWN_HOOK_PRIORITY);
//RM初始化
resourceManager.init(conf);
//RM启动
resourceManager.start();
}
} catch (Throwable t) {
LOG.fatal("Error starting ResourceManager", t);
System.exit(-1);
}
}
RM初始化
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
notifyListeners();
}
} catch (Exception e) {
noteFailure(e);
ServiceOperations.stopQuietly(LOG, this);
throw ServiceStateException.convert(e);
}
}
}
}
@Override
protected void serviceInit(Configuration conf) throws Exception {
this.conf = conf;
this.rmContext = new RMContextImpl();
this.configurationProvider =
ConfigurationProviderFactory.getConfigurationProvider(conf);
this.configurationProvider.init(this.conf);
rmContext.setConfigurationProvider(configurationProvider);
// load core-site.xml
InputStream coreSiteXMLInputStream =
this.configurationProvider.getConfigurationInputStream(this.conf,
YarnConfiguration.CORE_SITE_CONFIGURATION_FILE);
if (coreSiteXMLInputStream != null) {
this.conf.addResource(coreSiteXMLInputStream);
}
// Do refreshUserToGroupsMappings with loaded core-site.xml
Groups.getUserToGroupsMappingServiceWithLoadedConfiguration(this.conf)
.refresh();
// Do refreshSuperUserGroupsConfiguration with loaded core-site.xml
// Or use RM specific configurations to overwrite the common ones first
// if they exist
RMServerUtils.processRMProxyUsersConf(conf);
ProxyUsers.refreshSuperUserGroupsConfiguration(this.conf);
// load yarn-site.xml
InputStream yarnSiteXMLInputStream =
this.configurationProvider.getConfigurationInputStream(this.conf,
YarnConfiguration.YARN_SITE_CONFIGURATION_FILE);
if (yarnSiteXMLInputStream != null) {
this.conf.addResource(yarnSiteXMLInputStream);
}
validateConfigs(this.conf);
// Set HA configuration should be done before login
this.rmContext.setHAEnabled(HAUtil.isHAEnabled(this.conf));
if (this.rmContext.isHAEnabled()) {
HAUtil.verifyAndSetConfiguration(this.conf);
}
// Set UGI and do login
// If security is enabled, use login user
// If security is not enabled, use current user
this.rmLoginUGI = UserGroupInformation.getCurrentUser();
try {
doSecureLogin();
} catch(IOException ie) {
throw new YarnRuntimeException("Failed to login", ie);
}
//前面的代码关键就做了初始化配置文件,读取配置文件,设置配置文件上下文这类的事情,就不多做分析了
// register the handlers for all AlwaysOn services using setupDispatcher().
// 注册了一个调度器,用于内部事件调度处理:new AsyncDispatcher(),
//并且为其注册一个事件类型-handler元素
//<RMFatalEventType.class,RMFatalEventDispatcher>
rmDispatcher = setupDispatcher();
//rmDispatcher也是一个service,将其添加到RM的serviceList成员中
addIfService(rmDispatcher);
rmContext.setDispatcher(rmDispatcher);
adminService = createAdminService();
addService(adminService);
rmContext.setRMAdminService(adminService);
rmContext.setYarnConfiguration(conf);
//
createAndInitActiveServices();
webAppAddress = WebAppUtils.getWebAppBindURL(this.conf,
YarnConfiguration.RM_BIND_HOST,
WebAppUtils.getRMWebAppURLWithoutScheme(this.conf));
super.serviceInit(this.conf);
}
附录
hadoop工程的Configuartion架构分析
父类Configuration的资源加载:
static{
//print deprecation warning if hadoop-site.xml is found in classpath
ClassLoader cL = Thread.currentThread().getContextClassLoader();
if (cL == null) {
cL = Configuration.class.getClassLoader();
}
if(cL.getResource("hadoop-site.xml")!=null) {
LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
"Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
+ "mapred-site.xml and hdfs-site.xml to override properties of " +
"core-default.xml, mapred-default.xml and hdfs-default.xml " +
"respectively");
}
addDefaultResource("core-default.xml");
addDefaultResource("core-site.xml");
}
子类YarnConfiguration的资源加载:
static {
addDeprecatedKeys();
Configuration.addDefaultResource(YARN_DEFAULT_CONFIGURATION_FILE);
Configuration.addDefaultResource(YARN_SITE_CONFIGURATION_FILE);
}
static {
addDeprecatedKeys();
// adds the default resources
Configuration.addDefaultResource("hdfs-default.xml");
Configuration.addDefaultResource("hdfs-site.xml");
}
子类JobConf的资源加载:
static{
ConfigUtil.loadResources();
}
/**
* Adds all the deprecated keys. Loads mapred-default.xml and mapred-site.xml
*/
public static void loadResources() {
addDeprecatedKeys();
Configuration.addDefaultResource("mapred-default.xml");
Configuration.addDefaultResource("mapred-site.xml");
Configuration.addDefaultResource("yarn-default.xml");
Configuration.addDefaultResource("yarn-site.xml");
}
RM类继承关系
组件状态
public interface Service extends Closeable {
/**
* Service states
*/
public enum STATE {
/** Constructed but not initialized */
NOTINITED(0, "NOTINITED"),
/** Initialized but not started or stopped */
INITED(1, "INITED"),
/** started and not stopped */
STARTED(2, "STARTED"),
/** stopped. No further state transitions are permitted */
STOPPED(3, "STOPPED");
AsyncDispatcher分析
/**
- Dispatches {@link Event}s in a separate thread. Currently only single thread
- does that. Potentially there could be multiple channels for each event type
- class and a thread pool can be used to dispatch the events.
*/
核心类AsyncDispatcher:异步事件分发器(Yarn中最底层的总管道)
使用BlockingQueue存储事件,并维护一个事件类型和handler的对应map。
public class AsyncDispatcher extends AbstractService implements Dispatcher {
主要的属性
(1)事件队列: BlockingQueue<Event> eventQueue;
(2)事件分发器: Map<Class<? extends Enum>, EventHandler> eventDispatchers
(3)处理事件的线程 Thread eventHandlingThread
主要的方法
1、从eventQueue中取出事件以及处理事件
(1)createThread():返回一个Runnable对象,该线程类对象有一个while循环,不断从eventQueue中取出事件(RM启动之后),event = eventQueue.take();然后将事件分发出去dispatch(event)。
(2)dispatch(event):首先得到事件的类型,然后从eventDispatchers中根据事件类型得到相应的事件处理器EventHandler,然后EventHandler.handle(event)对事件进行处理。
2、向eventQueue中添加事件
AsyncDispatcher 的内部类GenericEventHandler implements EventHanler的handle(event)方法向eventQueue中添加事件eventQueue.put(event);
}
ResourceManager类中的Dispatcher类
ResourceManager类中定义了许多EventDispatcher内部类
RM中存在不同的事件,每种事件具有不同的类型,同一类型的事件交给一个XXXEventDispatcher,XXXEventDispatcher将事件交给真正的事件处理实体进行处理。
RM中定义的XXXEventDispatcher内部类如下:
|事件分发器|处理的事件|事件类型|事件处理实体|
|SchedulerEventDispatcher|SchedulerEvent|enum SchedulerEventType|ResourceScheduler|
|RMFatalEventDispatcher|enum RMFatalEventType|enum RMFatalEventType|System.exit(status)|
|ApplicationEventDispatcher|RMAppEvent|RMAppEventType|RMAppImpl|
|RMContainerPreemptEventDispatcher|ContainerPreemptEvent|ContainerPreemptEventType|CapacityScheduler|
ApplicationAttemptEventDispatcher|RMAppAttemptEvent|RMAppAttemptEventType|RMAppAttemptImpl|
|NodeEventDispatcher|RMNodeEvent|RMNodeEventType|RMNodeImpl|