Flink Yarn Java Api Application 模式发布应用

背景

最近公司在做实时数仓,技术上选择flink作为数据处理引擎,同时需要将实时数仓cdc(ODS层),建模(DWD)等逻辑进行功能化集成到数据仓库中方便数仓开发人员进行使用。
由于离线平台使用Yarn作为资源管理器而flink也支持yarn,为通过api进行flink应用的启动停止最终使用flink yarn application 模式进行发布。

Flink Yarn 介绍

下图为flink官方架构图,主要说明了flink 应用在yarn application模式下用户jar包的执行过程。

  1. 将用户uber-jar上传到hdfs,等到yarn container启动时直接通过hdfs下载
  2. 通过flink client 提交命令到yarn resource manger
  3. 分配yarn app master
  4. 由于flink 是主从架构且支持并行执行因此yarn会根据提交的配置启动多个yarn container 分别执行flink job manager跟task mananger
    Flink Yarn Java Api Application 模式发布应用_第1张图片

当然flink standalone 模式提供了rest api可以控制flink jar的执行但不是我们的需求所以放弃

中台集成架构

由于中台使用springcloud 架构且只负责flink 用户jar的启动发布与监控管理因此通过flink cli 源码进行分析后将相关逻辑进行整理并与中台集成如下图所示
Flink Yarn Java Api Application 模式发布应用_第2张图片

  1. 通过平台将flink 用户jar 名称,启动参数等进行管理
  2. 通过yarn api 提交用户jar 到yarn集群
  3. flink 用户应用通过http回调可以自定义配置信息并执行

以上逻辑是在分析完flink cli 启动逻辑后将代码

Flink CLI 启动源码分析

下图为flink 启动脚本对应的源代码逻辑

  1. 启动入口为CliFrontend主函数
  2. 加载配置信息命令行信息
  3. 根据传入参数使用那种命令模式
  4. 由于本文为application mode 所以通过yarn进行发布这也是中台中需要的逻辑
  5. 通过JAVA SPI进行加载要执行的deployer
  6. 最终将应用发布到yarn
    Flink Yarn Java Api Application 模式发布应用_第3张图片

代码演示

核心代码逻辑如下,具体jar包版本需要根据实际情况进行分析并调整

 String flinkLibs = "hdfs://GWNS/tmp/lib";
        String userJarPath = "hdfs://GWNS/tmp/lib/WordCount.jar";
        String flinkDistJar = "hdfs://GWNS/tmp/lib/flink-dist_2.12-1.12.0.jar";

        YarnClient yarnClient = YarnClient.createYarnClient();
        YarnConfiguration yarnConfiguration = new YarnConfiguration();
        yarnClient.init(yarnConfiguration);
        yarnClient.start();

        YarnClusterInformationRetriever clusterInformationRetriever = YarnClientYarnClusterInformationRetriever
                .create(yarnClient);
        //获取flink的配置
        Configuration flinkConfiguration = GlobalConfiguration.loadConfiguration(
                configurationDirectory);
//        flinkConfiguration.set(CheckpointingOptions.INCREMENTAL_CHECKPOINTS, true);
        flinkConfiguration.set(
                PipelineOptions.JARS,
                Collections.singletonList(
                        userJarPath));
        YarnLogConfigUtil.setLogConfigFileInConfig(flinkConfiguration,configurationDirectory);
        Path remoteLib = new Path(flinkLibs);
        flinkConfiguration.set(
                YarnConfigOptions.PROVIDED_LIB_DIRS,
                Collections.singletonList(remoteLib.toString()));

        flinkConfiguration.set(
                YarnConfigOptions.FLINK_DIST_JAR,
                flinkDistJar);
        //设置为application模式
        flinkConfiguration.set(
                DeploymentOptions.TARGET,
                YarnDeploymentTarget.APPLICATION.getName());
        //yarn application name
        flinkConfiguration.set(YarnConfigOptions.APPLICATION_NAME, "test-yarn-api");
        //设置配置,可以设置很多
        flinkConfiguration.set(JobManagerOptions.TOTAL_PROCESS_MEMORY, MemorySize.parse("1024",MEGA_BYTES));
        flinkConfiguration.set(TaskManagerOptions.TOTAL_PROCESS_MEMORY, MemorySize.parse("1024",MEGA_BYTES));

        ClusterSpecification clusterSpecification = new ClusterSpecification.ClusterSpecificationBuilder()
                .createClusterSpecification();

//		设置用户jar的参数和主类
        ApplicationConfiguration appConfig = new ApplicationConfiguration(params,"org.apache.flink.examples.java.wordcount.WordCount");


        YarnClusterDescriptor yarnClusterDescriptor = new YarnClusterDescriptor(
                flinkConfiguration,
                yarnConfiguration,
                yarnClient,
                clusterInformationRetriever,
                true);
        ClusterClientProvider<ApplicationId> clusterClientProvider = null;
        try {
            clusterClientProvider = yarnClusterDescriptor.deployApplicationCluster(clusterSpecification,appConfig);
        } catch (ClusterDeploymentException e){
            e.printStackTrace();
        }

总结

本方案目前已经在公司得到验证,同时欢迎更多交流

你可能感兴趣的:(flink,分享,flink)