Flink 一次打包多个环境运行

前言

入坑大数据之前,一直在做业务开发,必然是少不了用springboot。springboot 可以根据 spring.profiles.active来指定启动的环境信息,一个包可以运用多个环境,也在一定程度上避免了线上和开发测试不一致的情况,那么在Flink 中该如何实现再加载环境时指定环境信息呢,是否有flink.profiles.active

当然Flink 没有提供类似的功能,我们针对Flink 提供的工具方法稍加加工即可实现。

实现

针对于flink读取配置ParameterTool 提供了很多取配置的方法,使用env.getConfig().setGlobalJobParameters(parameterTool)
它可以传递 Configuration 中的参数到 Rich 函数中,使用open() 可以获取到配置中的参数。 我们可以从ParameterTool入手,我们可以根据启动指定的args[],来决定加载什么环境的配置,当然我们需要约定好,比如说启动时指定--flink.profiles.active test 来读取我们test对应的环境信息 , 利用
ParameterTool.fromArgs(args).get("flink.profiles.active")可以获取到 flink.profiles.active 值,如果没有值就读取默认位置的配置文件。如果有值我们可以采用路径区来分环境,读取不同环境下的配置信息,当然springboot 还有配置优先级,可以meger 默认配置文件中的配置,ParameterTool提供了ParameterTool#mergeWith()方法。具体代码实现如下:

/**
 * @author liweigao
 * @date 2021/7/28 下午6:13
 */
@Slf4j
public class EnvOperation {

    private EnvOperation() {
        throw new RuntimeException("not support instantiation by other!");
    }

    private static final String ENV = "flink.profiles.active";

    private static final String FILE_CHARACTER = "/";

    /**
     * @param args   参数
     * @param tclass class
     * @param name   name of the desired resource
     * @return inputStream
     */
    public static InputStream getEnvStream(String[] args, Class tclass, String name) {
        ParameterTool fromArgs = fromArgs(args);
        String path = getEnvPath(fromArgs);
        return getEnvStream(path, tclass, name);
    }

    /**
     * 解析文件
     *
     * @param path   解析激活的环境变量
     * @param tclass class
     * @param name   文件名称
     * @return inputStream
     */
    private static InputStream getEnvStream(String path, Class tclass, String name) {
        if (Strings.isBlank(path)) {
            log.info("profiles active is : default");
            return getDefaultEnvStream(tclass, name);
        } else {
            if (!name.startsWith(FILE_CHARACTER)) {
                name = FILE_CHARACTER + name;
            }
            log.info("profiles active is : {}", path);
            return tclass.getResourceAsStream(FILE_CHARACTER + path + name);
        }
    }

    /**
     * 获取指定环境的配置信息
     *
     * @param path   路径
     * @param tclass class
     * @param name   文件名称
     * @return inputStream
     */
    private static InputStream getSpeciallyEnvStream(String path, Class tclass, String name) {
        if (!name.startsWith(FILE_CHARACTER)) {
            name = FILE_CHARACTER + name;
        }
        return tclass.getResourceAsStream(FILE_CHARACTER + path + name);
    }

    /**
     * @param tclass class
     * @param name   文件名称
     * @return inputStream
     */
    private static InputStream getDefaultEnvStream(Class tclass, String name) {
        return tclass.getResourceAsStream(name);
    }

    /**
     * @param args 参数
     * @param name name of the desired resource
     * @return inputStream
     */
    public static InputStream getEnvStream(String[] args, String name) {

        return getEnvStream(args, EnvOperation.class, name);
    }

    /**
     * 获取指定环境路径
     *
     * @param tool args
     * @return path
     * @see {@link Utils#getKeyFromArgs(String[], int)}
     */
    private static String getEnvPath(ParameterTool tool) {
        return tool.get(ENV);

    }

    private static ParameterTool fromArgs(String[] args) {
        return ParameterTool.fromArgs(args);
    }

    public static ParameterTool getParameterToolMergeDefault(String[] args, Class tclass, String name) throws IOException {

        ParameterTool fromArgs = fromArgs(args);
        String path = getEnvPath(fromArgs);
        ParameterTool defaultTool = getParameterToolForInputStream(getDefaultEnvStream(tclass, name));
        if (Strings.isBlank(path)) {
            log.info("profiles active is : default");
            log.info("default config mergeWith args config");
            // formArgs data is UnmodifiableMap
            Map<String, String> map = fromArgs.toMap();
            map = Maps.newHashMap(map);
            map.put(ENV, "default");
            fromArgs = ParameterTool.fromMap(map);
            return defaultTool.mergeWith(fromArgs);

        } else {
            log.info("profiles active is : {}", path);
            ParameterTool active = getParameterToolForInputStream(getSpeciallyEnvStream(path, tclass, name));
            log.info("default config mergeWith {} config", path);
            active = defaultTool.mergeWith(active);
            log.info("{} config is mergeWith args config", path);
            return active.mergeWith(fromArgs);
        }
    }

    private static ParameterTool getParameterToolForInputStream(InputStream inputStream) throws IOException {

        ParameterTool parameterTool = ParameterTool.fromArgs(new String[0]);
        if (Objects.nonNull(inputStream)) {
            parameterTool = ParameterTool.fromPropertiesFile(inputStream);
        } else {
            log.debug("profiles path is non-existent");
        }
        return parameterTool;
    }

}

获取配置时:

             final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        ParameterTool parameterTool = EnvOperation.getParameterToolMergeDefault(args, Application.class,
                "/application.properties");
        //设置全局配置
        env.getConfig().setGlobalJobParameters(parameterTool);;      

parameterTool 对象即为指定 flink.profiles.active 对应的环境信息。
配置目录结构

├── application.properties
├── test
│   └── application.properties
└── dev
    └── application.properties

当我们部署standalone 、yarn(session 、 per job or application moudle)时 启动命令需要加–flink.profiles.active [环境信息], 即可实现启动指定环境信息

总结

以上拙见,毕竟才入坑,欢迎交流,本次实现为不同环境按照目录来区分,当然我们也可以完全做到跟springboot 加载环境信息一样的功能,当然目前已经满足我们目前的需求了~点到为止,不做复杂的轮子。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,以下是一个 Flink Table 读取 Kafka 多个表的示例代码,使用的是 Flink 1.17.0 版本,并且可以通过 Maven 构建: ```java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.EnvironmentSettings; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; import org.apache.flink.table.descriptors.Kafka; import org.apache.flink.table.descriptors.Schema; import org.apache.flink.table.descriptors.FormatDescriptor; import org.apache.flink.table.descriptors.Json; import org.apache.flink.table.descriptors.ConnectorDescriptor; public class FlinkKafkaTableDemo { public static void main(String[] args) throws Exception { // 创建 Flink Streaming 执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // 创建 Flink Table 执行环境 EnvironmentSettings settings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env, settings); // 定义 Kafka 连接器 ConnectorDescriptor kafkaConnector = new Kafka() .version("universal") .topic("topic-name") .startFromLatest() .property("bootstrap.servers", "localhost:9092") .property("group.id", "group-name"); // 定义 Schema Schema schema = new Schema() .field("field1", "VARCHAR") .field("field2", "BIGINT") .field("field3", "VARCHAR"); // 定义格式化器 FormatDescriptor format = new Json().failOnMissingField(true); // 注册 Kafka 连接器和 Schema tableEnv .connect(kafkaConnector) .withFormat(format) .withSchema(schema) .createTemporaryTable("table1"); // 注册另一个 Kafka 连接器和 Schema tableEnv .connect(kafkaConnector) .withFormat(format) .withSchema(schema) .createTemporaryTable("table2"); // 按照指定条件连接多个表 Table result = tableEnv.sqlQuery("SELECT t1.field1, t1.field2, t2.field3 FROM table1 t1 JOIN table2 t2 ON t1.field1 = t2.field1"); // 输出结果 result.printSchema(); result.execute().print(); // 执行任务 env.execute("Flink Kafka Table Demo"); } } ``` 你可以将这个代码保存为 `FlinkKafkaTableDemo.java` 文件,并在同一目录下创建一个 `pom.xml` 文件,内容如下: ```xml <project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>flink-kafka-table-demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.12</artifactId> <version>1.17.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-table-api-java-bridge_2.12</artifactId> <version>1.17.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-kafka_2.12</artifactId> <version>1.17.0</version> </dependency> </dependencies> </project> ``` 然后,在命令行中进入到该目录,并执行以下命令进行编译和打包: ``` mvn package ``` 编译完成后,在 `target` 目录下会生成一个名为 `flink-kafka-table-demo-1.0-SNAPSHOT.jar` 的可执行 JAR 文件。你可以使用以下命令在 Flink运行它: ``` ./bin/flink run flink-kafka-table-demo-1.0-SNAPSHOT.jar ``` 注意,以上命令中的 `./bin/flink` 可能需要根据你的实际情况调整。另外,示例中的 Kafka 版本为 `universal`,因此可以适用于不同版本的 Kafka。如果你的 Kafka 版本与本示例不同,请根据实际情况调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值