系列文章目录
Flink源码分析:Flink SQL Submit源码提交过程
Flink源码分析:基于事件时间场景下WaterMark源码分析
Flink源码分析: 重启策略机制RestartStrategy
Flink源码分析: Flink JDBC Upsert模式实现原理
前言
上期解读了Flink SQL的提交源码,有兴趣的同学可以看下之前那篇文章。
那么如果我们用DataStream API开发Flink项目时,Flink又是怎么提交Jar包运行程序的呢?下面给大家讲解下Flink是如何运行API程序的。
在Flink内提交任务时,命令行命令入下:flink run -c xxx.jar
通过定位代码,我们发现CliFrontend是入口类;
找到parseAndRun方法,可以看到这里封装了提交Jar包的一些行为操作。我们点击
run(params)看下这个方法:
从中我们得到run方法主要经过以下几个环节:
-
CliFrontendParser.getRunCommandOptions() 获取加载配置
-
getJobJarAndDependencies(programOptions) 加载job Jar包和依赖包
-
getEffectiveConfiguration(activeCommandLine, commandLine, programOptions, jobJars)获取有效的配置
-
executeProgram(effectiveConfiguration, program) 执行程序,提交给JobManager
接下来我们主要看下 executeProgram这个方法
public static void executeProgram(
PipelineExecutorServiceLoader executorServiceLoader,
Configuration configuration,
PackagedProgram program,
boolean enforceSingleJobExecution,
boolean suppressSysout)
throws ProgramInvocationException {
checkNotNull(executorServiceLoader);
final ClassLoader userCodeClassLoader = program.getUserCodeClassLoader();
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(userCodeClassLoader);
LOG.info(
"Starting program (detached: {})",
!configuration.getBoolean(DeploymentOptions.ATTACHED));
ContextEnvironment.setAsContext(
executorServiceLoader,
configuration,
userCodeClassLoader,
enforceSingleJobExecution,
suppressSysout);
StreamContextEnvironment.setAsContext(
executorServiceLoader,
configuration,
userCodeClassLoader,
enforceSingleJobExecution,
suppressSysout);
try {
program.invokeInteractiveModeForExecution();
} finally {
ContextEnvironment.unsetAsContext();
StreamContextEnvironment.unsetAsContext();
}
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
封装了一个PackagedProgram对象专门用来解析Jar包,搜索程序入口,通过这个对象可以加载Jar包Class文件:
final ClassLoader userCodeClassLoader = program.getUserCodeClassLoader();
初始化一个线程,开启上下文:
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
通过反射把我们程序入口的main方法加载到线程中:
Thread.currentThread().setContextClassLoader(userCodeClassLoader);