flink是近来比较热门的实时流计算引擎,相信大家对于其使用并不陌生。但是使用怎么能是我们追求的重点,本着打破砂锅问到底的态度(其实就是上班划水,不要找借口了)
我们一起从头开始,研究flink源码,在这之中无形的拓宽知识面。既然开始,就从最前面开始,首先从sh脚本开始分析
1、我们在本地集群运行时,首先使用到的命令就是start-cluster.sh脚本启动,查看脚本内容我们不难发现,不管是启动HA模式,还是非HA模式,都会执行jobmanager.sh脚本,这里的STARTSTOP=$1,其实就是STARTSTOP=start,所以这里会走flink-daemon.sh,在flink-daemon.sh我们可以看到指向的启动类,
我们主要研究一下单机集群启动类org.apache.flink.runtime.entrypoint.standalonesessionclusterentrypoint类
2、那废话不多说,我们先查看StandaloneSessionClusterEntrypoint启动源码,StandaloneSessionClusterEntrypoint继承自SessionClusterEntrypoint
主要执行逻辑我将以注释的形式标注在代码之中
// startup checks and logging
// 进行启动检查,获取启动环境信息,如版本,scala版本,git提交号,jvm版本,hadoop版本,javahome等
EnvironmentInformation.logEnvironmentInfo(LOG, StandaloneSessionClusterEntrypoint.class.getSimpleName(), args);
// 捕捉系统信号windows包含:终止(TERM),INT(键盘中断);其它系统多包含:HUP(终端挂起或者控制进程终止)
SignalHandler.register(LOG);
// 注册JVM关闭的钩子函数 设置5秒延迟退出
JvmShutdownSafeguard.installAsShutdownHook(LOG);
// 获取启动行参数,使用的是org.apache.commons.cli
// 所有的启动参数都写在了org.apache.flink.runtime.entrypoint.parser.CommandLineOptions类中
// 包括:
// c configDir: Directory which contains the configuration file flink-conf.yml.
// r webui-port: Port for the rest endpoint and the web UI.
// D property=value: use value for given property
// h host: Hostname for the RPC service.
// x executionMode: Deprecated option
EntrypointClusterConfiguration entrypointClusterConfiguration = null;
final CommandLineParser commandLineParser = new CommandLineParser<>(new EntrypointClusterConfigurationParserFactory());
try {
entrypointClusterConfiguration = commandLineParser.parse(args);
} catch (FlinkParseException e) {
LOG.error("Could not parse command line arguments {}.", args, e);
commandLineParser.printHelp(StandaloneSessionClusterEntrypoint.class.getSimpleName());
System.exit(1);
}
// 获取到参数
Configuration configuration = loadConfiguration(entrypointClusterConfiguration);
StandaloneSessionClusterEntrypoint entrypoint = new StandaloneSessionClusterEntrypoint(configuration);
// 运行 执行父类方法
ClusterEntrypoint.runClusterEntrypoint(entrypoint);
3、然后我们看看运行后,进入SessionClusterEntrypoint的startCluster方法
// 加载插件,从文件系统找jar包
PluginManager pluginManager = PluginUtils.createPluginManagerFromRootFolder(configuration);
// 初始化共享文件系统设置,会将文件系统映射为url
configureFileSystems(configuration, pluginManager);
// 初始化安全上下文:其中为进程范围的安全配置,使用可用的安全模块(即Hadoop、JAAS)应用配置。
SecurityContext securityContext = installSecurityContext(configuration);
securityContext.runSecured((Callable) () -> {
runCluster(configuration, pluginManager);
return null;
});
4、接下来进入runCluster方法之后,由于展开来讲过多,具体每个模块我将在后续文章一一解析,我将按照代码执行的顺序按行解释,大家可以按照源码对照分析
一、初始化集群服务
initializeServices(configuration, pluginManager);
创建通用RPC服务,会从配置中获取地址,端口范围,绑定本地host和端口号,其中RPC服务使用的是AKKA
createHaServices(configuration, ioExecutor);
其中共有三种模式:
1、NONE:创建高可用服务,根据资源管理器地址,调度地址,监控地址,生成单机高可用服务
2、ZOOKEEPER:使用ZooKeeper,服务将数据存储在ZooKeeper的节点中,结构如下,其中每个集群独立目录:
/flink
/cluster_id_1/resource_manager_lock
/job-id-1/job_manager_lock
/checkpoints/latest
/latest-1
/latest-2
/job-id-2/job_manager_lock
/cluster_id_2/resource_manager_lock
/job-id-1/job_manager_lock
/checkpoints/latest
/latest-1
/persisted_job_graph
3、FACTORY_CLASS:创建自定义的高可用服务
二、根据上述服务创建资源,调度,监控进程DispatcherResourceManagerComponent,并设置同步状态关闭,这之中还包含网关及查询服务检索器的创建,将在后续文章中一一详解。至此,启动结束。
总结:现在我们基本了解了flink启动读取运行参数,获取本地配置,并增加了JVM关闭钩子等一些我们平常开发不常用的一些方法,并大致了解flink的分布式的实现方案,在后续的文章中,我们具体看看flink是如何实现这些服务,并管理好task,保证服务的稳定性的。