flink-配置文件

在基于java8的flink项目中,我有一个配置文件env.properties用来切换配置,内容如下:
#env_name=cn_clound2-test
#env_cfg=cn-cloud2-new-tsp-conf-test.properties


###########CN Cloud V2 ENV STAG########
#env_name=cn_clound2-stag
#env_cfg=cn-cloud2-new-tsp-conf-stag.properties


###########CN Cloud V2 ENV PRO########
env_name=cn_clound2-pro
env_cfg=cn-cloud2-new-tsp-conf-pro.properties

然后我是这样定义一个类来加载管理配置文件;
package com.ecarx.sumatra.data.tab.conf;

import java.io.Serializable;
import java.util.Properties;

import org.apache.flink.api.java.utils.ParameterTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EnvConfig implements Serializable {
private static final Logger LOG = LoggerFactory.getLogger(EnvConfig.class);
private static String envName;
private static String envConfig;
private static Properties env;

public static void main(String[] args) {
init();
for (Object key : env.keySet()) {
System.out.println(key + "=" + env.getProperty(key.toString()));
}
}

static {
try {
ParameterTool parameterTool = ParameterTool
.fromPropertiesFile(EnvConfig.class.getResourceAsStream("/env.properties"));
envName = parameterTool.get("env_name");
envConfig = parameterTool.get("env_cfg");

LOG.info("the application run on :{},{}", envConfig, envName);

if (envConfig != null) {
parameterTool = ParameterTool.fromPropertiesFile(EnvConfig.class.getResourceAsStream("/" + envConfig));
env = parameterTool.getProperties();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void init() {
System.out.println("Load config file.");
}

public static String getValue(String key) {
return env.getProperty(key);
}

public static String getEnvConfig() {
return envConfig;
}

public static String getEnvName() {
return envName;
}
}
使用的时候:
EnvConfig.init();
AppContext context = new AppContext(EnvConfig.getEnvConfig(), true);
context.setTaskName("EcarxCloud2TspDataProcessApp-" + EnvConfig.getEnvName());
其中AppContext类如下:(注意他这里合并了系统的配置)
package com.ecarx.sumatra.data.common;

import java.io.Serializable;
import java.util.Properties;

import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.java.utils.ParameterTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AppContext implements Serializable {
private String taskName;
private String configFile;
private SimpleStringSchema messageDeserializer;
private Properties taskConf;
private Properties appConf;

public AppContext(String configFile, boolean defaultSchema) {
super();
this.configFile = configFile;
this.appConf = this.initCofig();
if (defaultSchema) {
this.messageDeserializer = new SimpleStringSchema();
}
}

private Properties initCofig() {
final Logger log = LoggerFactory.getLogger(AppContext.class);
try {
ParameterTool parameterTool = ParameterTool
.fromPropertiesFile(MessageImport.class.getResourceAsStream("/" + configFile))
.mergeWith(ParameterTool.fromSystemProperties());
Properties pro = parameterTool.getProperties();
String topics = pro.getProperty("metrics.topic");
String broke_cluster = pro.getProperty("kafka.brokers");
String groupId = pro.getProperty("kafka.group.id");

this.taskConf = new Properties();
this.taskConf.setProperty("bootstrap.servers", broke_cluster);
this.taskConf.setProperty("topics", topics);
this.taskConf.setProperty("group.id", groupId);
this.taskConf.setProperty("auto.offset.reset", "earliest");

log.info("init config ,{}", this.taskConf.toString());
return pro;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public String getTaskName() {
return taskName;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public String getConfigFile() {
return configFile;
}

public void setConfigFile(String configFile) {
this.configFile = configFile;
}

public SimpleStringSchema getMessageDeserializer() {
return messageDeserializer;
}

public void setMessageDeserializer(SimpleStringSchema messageDeserializer) {
this.messageDeserializer = messageDeserializer;
}

public Properties getAppConf() {
return appConf;
}

public Properties getKafkaConfig() {
Properties pro = new Properties();
pro.setProperty("bootstrap.servers", taskConf.getProperty("bootstrap.servers"));
pro.setProperty("group.id", taskConf.getProperty("group.id"));
pro.setProperty("auto.offset.reset", taskConf.getProperty("auto.offset.reset"));
pro.setProperty("topics", taskConf.getProperty("topics"));
return pro;
}
}

 

自定义配置类:

 

复制代码
package com.ecarx.sumatra.data.tab.conf;

import org.apache.flink.api.java.utils.ParameterTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Optional;
import java.util.Properties;

public class ConfigManager {
    private static final Logger LOG = LoggerFactory.getLogger(ConfigManager.class);
    private static ParameterTool parameterTool;

    /**
     * 用于存储环境名称和配置文件名的静态内部类。
     */
    private static class EnvConfigPair {
        final String envName;
        final String configFileName;

        EnvConfigPair(String envName, String configFileName) {
            this.envName = envName;
            this.configFileName = configFileName;
        }
    }

    /**
     * 初始化配置管理器并加载指定环境的配置文件。
     */
    public static void init() {
        // 首先尝试从 env.properties 加载环境名称和配置文件名
        EnvConfigPair envAndCfg = loadEnvironmentAndConfigFromProperties();

        if (envAndCfg == null) {
            throw new RuntimeException("Environment and config file not properly specified in env.properties.");
        }

        // 使用加载到的环境名称和配置文件名初始化配置
        initializeWithEnvAndConfig(envAndCfg.envName, envAndCfg.configFileName);
    }

    private static void initializeWithEnvAndConfig(String envName, String configFileName) {
        String configFilePath = String.format("/%s", configFileName);

        try (InputStream configStream = ConfigManager.class.getResourceAsStream(configFilePath)) {
            if (configStream == null) {
                throw new IOException("Configuration file not found: " + configFilePath);
            }
            parameterTool = ParameterTool.fromPropertiesFile(configStream);

            LOG.info("Application running on environment: {}", envName);
            LOG.debug("Loaded configuration from: {}", configFilePath);
        } catch (IOException e) {
            LOG.error("Failed to load configuration files.", e);
            throw new RuntimeException("Initialization failed due to configuration loading error.", e);
        }
    }

    private static EnvConfigPair loadEnvironmentAndConfigFromProperties() {
        try (InputStream envStream = ConfigManager.class.getResourceAsStream("/env.properties")) {
            if (envStream != null) {
                Properties envProps = new Properties();
                envProps.load(envStream);
                String envName = envProps.getProperty("env_name");
                String configFileName = envProps.getProperty("env_cfg");

                if (envName != null && configFileName != null) {
                    return new EnvConfigPair(envName, configFileName);
                }
            }
        } catch (IOException e) {
            LOG.warn("Failed to load env.properties, falling back to default settings.", e);
        }
        return null;
    }

    /**
     * 获取配置项的值。
     *
     * @param key 配置项的键
     * @return 对应的值,如果没有找到则返回 null
     */
    public static String getValue(String key) {
        return Optional.ofNullable(parameterTool).map(tool -> tool.get(key)).orElse(null);
    }

    /**
     * 获取指定类型的配置项值。
     *
     * @param <T>   配置项类型
     * @param key   配置项的键
     * @param clazz 配置项的目标类型
     * @return 对应的值,如果没有找到则返回 null
     */
    public static <T> T getValue(String key, Class<T> clazz) {
        if (clazz == Integer.class) {
            return clazz.cast(Optional.ofNullable(parameterTool)
                    .map(tool -> tool.getInt(key))
                    .orElse(null));
        } else if (clazz == Boolean.class) {
            return clazz.cast(Optional.ofNullable(parameterTool)
                    .map(tool -> tool.getBoolean(key))
                    .orElse(null));
        } else {
            return clazz.cast(getValue(key));
        }
    }

    /**
     * 主方法仅用于测试目的。
     */
    public static void main(String[] args) {
        // 通过 env.properties 指定环境和配置文件
        init();

        if (parameterTool != null) {
            parameterTool.toMap().forEach((key, value) -> System.out.println(key + "=" + value));
        }
    }
}
复制代码

 

当然,为了更好地展示如何使用配置文件来动态加载不同环境的配置,我将提供一个完整的案例,包括 `env.properties` 文件的设置、`ConfigManager` 类的使用以及如何在应用程序中读取这些配置。

### 1. 更新 `env.properties` 文件

首先,确保你的 `env.properties` 文件位于项目的资源目录(如 `src/main/resources`)下,并包含以下内容:

```properties
########### CN Cloud V2 ENV TEST ########
#env_name=cn_clound2-test
#env_cfg=cn-cloud2-new-tsp-conf-test.properties

########### CN Cloud V2 ENV STAG ########
#env_name=cn_clound2-stag
#env_cfg=cn-cloud2-new-tsp-conf-stag.properties

########### CN Cloud V2 ENV PRO ########
env_name=cn_clound2-pro
env_cfg=cn-cloud2-new-tsp-conf-pro.properties
```

你可以根据需要取消注释不同的部分以切换环境。

### 2. 创建具体的环境配置文件

接下来,在相同的资源目录下创建三个具体的配置文件,每个文件对应一个环境。例如:

- `cn-cloud2-new-tsp-conf-test.properties`
- `cn-cloud2-new-tsp-conf-stag.properties`
- `cn-cloud2-new-tsp-conf-pro.properties`

这里我们以 `cn-cloud2-new-tsp-conf-pro.properties` 为例,其他两个文件可以类似地创建:

```properties
# cn-cloud2-new-tsp-conf-pro.properties
app.name=CN Cloud V2 Production App
db.url=jdbc:mysql://prod-db.example.com:3306/app_db
db.user=prod_user
db.password=prod_password
service.endpoint=https://api.prod.example.com/v1
```

### 3. 使用 `ConfigManager` 类

假设你有一个应用程序入口类 `MainApp.java`,它使用 `ConfigManager` 来加载配置并启动应用:

```java
package com.ecarx.sumatra.data.tab.app;

import com.ecarx.sumatra.data.tab.conf.ConfigManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MainApp {
private static final Logger LOG = LoggerFactory.getLogger(MainApp.class);

public static void main(String[] args) {
// 初始化配置管理器,这会自动从 env.properties 加载环境和配置文件名
ConfigManager.init();

// 从配置文件中读取值
String appName = ConfigManager.getValue("app.name");
String dbUrl = ConfigManager.getValue("db.url");
String dbUser = ConfigManager.getValue("db.user");
String dbPassword = ConfigManager.getValue("db.password");
String serviceEndpoint = ConfigManager.getValue("service.endpoint");

// 打印读取到的配置信息
LOG.info("Application Name: {}", appName);
LOG.info("Database URL: {}", dbUrl);
LOG.info("Database User: {}", dbUser);
// 注意:不要打印密码或敏感信息到日志中
LOG.info("Service Endpoint: {}", serviceEndpoint);

// 这里可以继续实现你的业务逻辑...
}
}
```

### 4. 构建和运行应用

如果你使用的是 Maven 或 Gradle 构建工具,可以通过命令行构建和运行你的应用:

```bash
# 构建项目
mvn clean package

# 运行打包好的 JAR 文件
java -cp target/your-application.jar com.ecarx.sumatra.data.tab.app.MainApp
```

### 5. 切换环境

要切换环境,只需编辑 `env.properties` 文件中的 `env_name` 和 `env_cfg` 属性值,取消相应环境设置的注释,并重新启动应用程序。例如,将 `env_name=cn_clound2-pro` 改为 `env_name=cn_clound2-test` 并取消 `test` 部分的注释即可。

### 6. 示例输出

当您运行上述代码时,如果 `env.properties` 文件指定了 `pro` 环境,控制台输出可能会如下所示:

```plaintext
INFO com.ecarx.sumatra.data.tab.app.MainApp - Application Name: CN Cloud V2 Production App
INFO com.ecarx.sumatra.data.tab.app.MainApp - Database URL: jdbc:mysql://prod-db.example.com:3306/app_db
INFO com.ecarx.sumatra.data.tab.app.MainApp - Database User: prod_user
INFO com.ecarx.sumatra.data.tab.app.MainApp - Service Endpoint: https://api.prod.example.com/v1
```

通过这种方式,您可以轻松地根据不同的环境加载不同的配置文件,而无需修改代码或重新编译项目。这种灵活性不仅提高了开发效率,也使得部署和维护变得更加简单。

posted @   ---江北  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2019-12-23 kettle实战
TOP
点击右上角即可分享
微信分享提示