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
```
通过这种方式,您可以轻松地根据不同的环境加载不同的配置文件,而无需修改代码或重新编译项目。这种灵活性不仅提高了开发效率,也使得部署和维护变得更加简单。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2019-12-23 kettle实战