Scala中的环境特定配置
Posted
技术标签:
【中文标题】Scala中的环境特定配置【英文标题】:specific config by environment in Scala 【发布时间】:2014-03-03 16:25:07 【问题描述】:什么是在 Scala 中设置项目的好方法,该项目根据环境使用不同的配置。
我需要专门为开发、测试和生产环境设置不同的数据库(类似于Rails中所做的)
【问题讨论】:
【参考方案1】:我使用的另一个策略是使用includes。
我通常将我的 DEV 设置存储在 default application.conf
文件中,然后为其他环境创建一个新的 conf 文件并包含默认文件。
假设我的 DEV conf application.conf
如下所示:
myapp
server-address = "localhost"
server-port = 9000
some-other-setting = "cool !"
那么对于 PROD,我可以有另一个名为 prod.conf
的文件:
include "application"
# override default (DEV) settings
myapp
server-address = $PROD_SERVER_HOSTNAME
server-port = $PROD_SERVER_PORT
请注意,我仅覆盖了在 PROD 环境中更改的设置(some-other-setting
因此与 DEV 中的相同)。
配置引导代码不测试任何东西
...
val conf = ConfigFactory.load()
...
要从 DEV 切换到 PROD conf,只需传递一个带有要加载的配置文件名称的系统属性:
java -Dconfig.resource=prod.conf ...
在DEV中,不需要传递它,因为application.conf
会被default加载。
所以这里我们使用Typesafe Config的默认加载机制来实现这一点。
我创建了一个简单的project 来演示这种技术。随意克隆和试验。
【讨论】:
为了完整起见,我相信配置引导程序将是: val conf = ConfigFactory.load() def apply() = conf.getConfig("myapp") @ozeebee 由于某种原因这不起作用。请注意,我在 build.sbt 中添加了:fork in run := true
和 java -Dconfig.resource=stg.conf
。文件 stg.conf 在资源下,但我的配置仍然来自 application.conf。还要注意,当我使用:val conf = ConfigFactory.load("stg.conf")
时,我的配置会根据 stg.conf 加载。有什么想法吗?
@has981 不知道。我设置了一个简单的project 来演示这种技术。随意克隆和实验。
@ozeebee 您的代码在本地运行良好,但是当我使用 Docker 和 Kubernetes 在 flink 上部署此代码时它无法运行
@Kallz 抱歉,我不知道 flink;也许这个工具有自己的配置机制?【参考方案2】:
使用类型安全配置。像这样创建一个 Config 对象:
import com.typesafe.config._
object Config
val env = if (System.getenv("SCALA_ENV") == null) "development" else System.getenv("SCALA_ENV")
val conf = ConfigFactory.load()
def apply() = conf.getConfig(env)
然后在src/main/resources
文件夹中创建application.conf
文件:
development
your_app
databaseUrl = "jdbc:mysql://localhost:3306/dev_db"
databaseUser = "xxxx"
databasePassword = "xxxx"
test
your_app
databaseUrl = "jdbc:mysql://localhost:3306/test_db"
databaseUser = "xxxxx"
databasePassword = "xxxx"
现在,您可以从应用程序的任何位置访问配置:
Config().getString("your_app.databaseUrl")
如果您在运行应用程序时设置了环境(例如export SCALA_ENV=test
),它将考虑正确的配置部分。默认是开发
【讨论】:
我花了一段时间才找到这种保持系统属性首要地位的模式:ConfigFactory.defaultOverrides().withFallback(config2.getConfig(environment)).withFallback(config2); github.com/typesafehub/config/blob/master/examples/java/…【参考方案3】:我对 Daniel Cukiers 解决方案不允许默认值和覆盖的方式不满意,因此我对其进行了更改以充分利用它们。
您需要做的唯一配置是在系统上设置一个 ENVIRONMENT 变量(如果未设置,则默认为“dev”)
(Java方案,兼容Scala):
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class MyCompanyConfig
public final static Config base = ConfigFactory.load().getConfig("mycompany");
public final static String environment = System.getenv("ENVIRONMENT") == null ? "dev" : System.getenv("ENVIRONMENT");
/**
* Returns a subtree of the base configuration with environment settings applied.
*
* @param setting The subtree to return config for.
* @return A config with base in given setting, with environment modifications applied.
*/
public static Config load(String setting)
Config config = base.getConfig(setting);
if (config.hasPath(environment))
return config.getConfig(environment).withFallback(config);
return config;
这允许库中的单个 reference.conf 如下所示:
mycompany.module1
setting1 : "adefaultvalue"
url : "localhost"
test
// will be used where ENVIRONMENT="test"
url : "test.mycompany.com"
prod
// will be used where ENVIRONMENT="prod"
setting1 : "changethedefault"
url : "www.mycompany.com"
用法:
Config conf = MyCompanyConfig.load("module1")
【讨论】:
以上是关于Scala中的环境特定配置的主要内容,如果未能解决你的问题,请参考以下文章