插件有很多,azkaban預留的接口多種多樣,比如UserManager,Job,LoginAbstractAzkabanServlet等.
首先我要講的是,jobType插件的加載.jobType只需要由Executor來加載.
executor 配置參數
execution.dir.retention->執行目錄保存時間,單位毫秒,默認一天
azkaban.project.dir->工程運行時存放目錄
azkaban.jobtype.plugin.dir->jobType插件的目錄
public AzkabanExecutorServer(Props props) throws Exception {
this.props = props;
server = createJettyServer(props);//創建jetty server
executionLoader = new JdbcExecutorLoader(props);//executor Dao
projectLoader = new JdbcProjectLoader(props);//project dao
runnerManager = new FlowRunnerManager(props, executionLoader, projectLoader, getClass().getClassLoader());//作業流運行管理器
JmxJobMBeanManager.getInstance().initialize(props);
// make sure this happens before
configureJobCallback(props);
configureMBeanServer();
configureMetricReports();
SystemMemoryInfo.init(props.getInt("executor.memCheck.interval", 30));
loadCustomJMXAttributeProcessor(props);
try {
server.start();//啟動jetty server
} catch (Exception e) {
logger.error(e);
Utils.croak(e.getMessage(), 1);
}
insertExecutorEntryIntoDB();//往數據庫表進行注冊executor
dumpPortToFile();
logger.info("Started Executor Server on " + getExecutorHostPort());
if (props.getBoolean(ServerProperties.IS_METRICS_ENABLED, false)) {
startExecMetrics();
}
}
jobType管理是在FlowRunnerManager中進行的,在FlowRunnerManager構造函數中創建了
JobTypeManager.
//JobTypeManager構造函數
public JobTypeManager(String jobtypePluginDir, Props globalProperties,
ClassLoader parentClassLoader) {
this.jobTypePluginDir = jobtypePluginDir;//插件目錄,值跟azkaban.properties中azkaban.jobtype.plugin.dir有關
this.parentLoader = parentClassLoader;
this.globalProperties = globalProperties;//executor全局屬性配置,是executor.global.properties配置
loadPlugins();//加載插件
}
public void loadPlugins() throws JobTypeManagerException {
JobTypePluginSet plugins = new JobTypePluginSet();
loadDefaultTypes(plugins);//加載自帶插件
if (jobTypePluginDir != null) {
File pluginDir = new File(jobTypePluginDir);
if (pluginDir.exists()) {
logger
.info("Job type plugin directory set. Loading extra job types from "
+ pluginDir);
try {
loadPluginJobTypes(plugins);//加載第三方插件
} catch (Exception e) {
logger.info("Plugin jobtypes failed to load. " + e.getCause(), e);
throw new JobTypeManagerException(e);
}
}
}
以下是JobTypeManager加載第三方的任務類型
private void loadJobTypes(File pluginDir, JobTypePluginSet plugins)
throws JobTypeManagerException {
// Directory is the jobtypeName
String jobTypeName = pluginDir.getName();//目錄名就是任務類型名
logger.info("Loading plugin " + jobTypeName);
Props pluginJobProps = null;
Props pluginLoadProps = null;
File pluginJobPropsFile = new File(pluginDir, JOBTYPECONFFILE);
File pluginLoadPropsFile = new File(pluginDir, JOBTYPESYSCONFFILE);
if (!pluginLoadPropsFile.exists()) {
logger.info("Plugin load props file " + pluginLoadPropsFile
+ " not found.");
return;
}
try {
Props commonPluginJobProps = plugins.getCommonPluginJobProps();
Props commonPluginLoadProps = plugins.getCommonPluginLoadProps();
if (pluginJobPropsFile.exists()) {
pluginJobProps = new Props(commonPluginJobProps, pluginJobPropsFile);
} else {
pluginJobProps = new Props(commonPluginJobProps);
}
pluginLoadProps = new Props(commonPluginLoadProps, pluginLoadPropsFile);
pluginLoadProps.put("plugin.dir", pluginDir.getAbsolutePath());
pluginLoadProps = PropsUtils.resolveProps(pluginLoadProps);//替換變量
} catch (Exception e) {
logger.error("pluginLoadProps to help with debugging: " + pluginLoadProps);
throw new JobTypeManagerException("Failed to get jobtype properties"
+ e.getMessage(), e);
}
// Add properties into the plugin set
plugins.addPluginLoadProps(jobTypeName, pluginLoadProps);
if (pluginJobProps != null) {
plugins.addPluginJobProps(jobTypeName, pluginJobProps);
}
ClassLoader jobTypeLoader =
loadJobTypeClassLoader(pluginDir, jobTypeName, plugins);
String jobtypeClass = pluginLoadProps.get("jobtype.class");
Class<? extends Job> clazz = null;
try {
clazz = (Class<? extends Job>) jobTypeLoader.loadClass(jobtypeClass);
plugins.addPluginClass(jobTypeName, clazz);
} catch (ClassNotFoundException e) {
throw new JobTypeManagerException(e);
}
logger.info("Verifying job plugin " + jobTypeName);
try {
Props fakeSysProps = new Props(pluginLoadProps);
Props fakeJobProps = new Props(pluginJobProps);
@SuppressWarnings("unused")
Job job =
(Job) Utils.callConstructor(clazz, "dummy", fakeSysProps,
fakeJobProps, logger);
} catch (Throwable t) {
logger.info("Jobtype " + jobTypeName + " failed test!", t);
throw new JobExecutionException(t);
}
logger.info("Loaded jobtype " + jobTypeName + " " + jobtypeClass);
}
我們可以發現,其中有兩種配置,一個common.properties,一個是commonprivate.properties.
commonprivate.properties是用于在executor加載插件的時候所需要配置參數.common.properties是job啟動的時候需要通用配置參數.